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/CONTRIBUTING.md b/CONTRIBUTING.md index c6006ad1..2ab32cf9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,9 +26,9 @@ The Calibre-Web documentation is hosted in the Github [Wiki](https://github.com/ Do not open up a GitHub issue if the bug is a **security vulnerability** in Calibre-Web. Instead, please write an email to "ozzie.fernandez.isaacs@googlemail.com". -Ensure the ***bug was not already reported** by searching on GitHub under [Issues](https://github.com/janeczku/calibre-web/issues). Please also check if a solution for your problem can be found in the [wiki](https://github.com/janeczku/calibre-web/wiki). +Ensure the **bug was not already reported** by searching on GitHub under [Issues](https://github.com/janeczku/calibre-web/issues). Please also check if a solution for your problem can be found in the [wiki](https://github.com/janeczku/calibre-web/wiki). -If you're unable to find an **open issue** addressing the problem, open a [new one](https://github.com/janeczku/calibre-web/issues/new?assignees=&labels=&template=bug_report.md&title=). Be sure to include a **title** and **clear description**, as much relevant information as possible, the **issue form** helps you providing the right information. Deleting the form and just pasting the stack trace doesn't speed up fixing the problem. If your issue could be resolved, consider closing the issue. +If you're unable to find an **open issue** addressing the problem, open a [new one](https://github.com/janeczku/calibre-web/issues/new/choose). Be sure to include a **title** and **clear description**, as much relevant information as possible, the **issue form** helps you providing the right information. Deleting the form and just pasting the stack trace doesn't speed up fixing the problem. If your issue could be resolved, consider closing the issue. ### **Feature Request** diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 267f21ef..db8efe31 --- a/README.md +++ b/README.md @@ -1,98 +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, german, greek, hungarian, italian, japanese, khmer, korean, polish, russian, simplified and traditional chinese, spanish, swedish, turkish, ukrainian -- OPDS feed for eBook reader apps -- Filter and search by titles, authors, tags, series and language -- Create a custom book collection (shelves) -- Support for editing eBook metadata and deleting eBooks from Calibre library -- Support for converting eBooks through Calibre binaries -- Restrict eBook download to logged-in users -- Support for public user registration -- Send eBooks to Kindle devices 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-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/Configuration#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+ +- 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) -Optionally, to enable on-the-fly conversion from one ebook format to another when using the send-to-kindle feature, or during editing of ebooks metadata: +## Docker Images -[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. +Pre-built Docker images are available in the following Docker Hub repositories (maintained by the LinuxServer team): -[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`. +#### **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) -## Docker Images + 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. + + Both the Calibre-Web and Calibre-Mod images are automatically rebuilt on new releases and updates. -A pre-built Docker image is available in these Docker Hub repository (maintained by the LinuxServer team): + - Set "path to convertertool" to `/usr/bin/ebook-convert` + - Set "path to unrar" to `/usr/bin/unrar` -#### **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) +## Contributor Recognition - 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` +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. -# Contact +## Contact -Just reach us out on [Discord](https://discord.gg/h2VsJ2NEfB) +Join us on [Discord](https://discord.gg/h2VsJ2NEfB) -For further information, How To's and FAQ please check the [Wiki](https://github.com/janeczku/calibre-web/wiki) +For more information, How To's, and FAQs, please visit the [Wiki](https://github.com/janeczku/calibre-web/wiki) -# Contributing to Calibre-Web +## Contributing to Calibre-Web -Please have a look at our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md) +Check out our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md) diff --git a/SECURITY.md b/SECURITY.md index 1b93b5f9..e4ab1a8d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -35,9 +35,16 @@ To receive fixes for security vulnerabilities it is required to always upgrade t | V 0.6.16 | It's prevented to get the name of a private shelfs. Thanks to @nhiephon |CVE-2022-0405| | V 0.6.17 | The SSRF Protection can no longer be bypassed via an HTTP redirect. Thanks to @416e6e61 |CVE-2022-0767| | V 0.6.17 | The SSRF Protection can no longer be bypassed via 0.0.0.0 and it's ipv6 equivalent. Thanks to @r0hanSH |CVE-2022-0766| -| V 0.6.18 | Possible SQL Injection is prevented in user table Thanks to Iman Sharafaldin (Forward Security) || +| 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 128f13b6..2b7116e7 100644 --- a/babel.cfg +++ b/babel.cfg @@ -1,3 +1,4 @@ [python: **.py] + +# has to be executed with jinja2 >=2.9 to have autoescape enabled automatically [jinja2: **/templates/**.*ml] -extensions=jinja2.ext.autoescape,jinja2.ext.with_ \ No newline at end of file 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 1b68818d..1d081fe2 100644 --- a/cps/about.py +++ b/cps/about.py @@ -25,7 +25,6 @@ import platform import sqlite3 from collections import OrderedDict -import werkzeug import flask import flask_login import jinja2 @@ -37,41 +36,40 @@ from .render_template import render_title_template about = flask.Blueprint('about', __name__) -ret = dict() -req = dep_check.load_dependencys(False) -opt = dep_check.load_dependencys(True) +modules = dict() +req = dep_check.load_dependencies(False) +opt = dep_check.load_dependencies(True) for i in (req + opt): - ret[i[1]] = i[0] + modules[i[1]] = i[0] +modules['Jinja2'] = jinja2.__version__ +modules['pySqlite'] = sqlite3.version +modules['SQLite'] = sqlite3.sqlite_version +sorted_modules = OrderedDict((sorted(modules.items(), key=lambda x: x[0].casefold()))) -if constants.NIGHTLY_VERSION[0] == "$Format:%H$": - calibre_web_version = constants.STABLE_VERSION['version'] -else: - calibre_web_version = (constants.STABLE_VERSION['version'] + ' - ' - + constants.NIGHTLY_VERSION[0].replace('%', '%%') + ' - ' - + constants.NIGHTLY_VERSION[1].replace('%', '%%')) -if getattr(sys, 'frozen', False): - calibre_web_version += " - Exe-Version" -elif constants.HOME_CONFIG: - calibre_web_version += " - pyPi" - -_VERSIONS = OrderedDict( - Platform='{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()), - Python=sys.version, - Calibre_Web=calibre_web_version, - Werkzeug=werkzeug.__version__, - Jinja2=jinja2.__version__, - pySqlite=sqlite3.version, - SQLite=sqlite3.sqlite_version, -) -_VERSIONS.update(ret) -_VERSIONS.update(uploader.get_versions()) +def collect_stats(): + if constants.NIGHTLY_VERSION[0] == "$Format:%H$": + calibre_web_version = constants.STABLE_VERSION['version'].replace("b", " Beta") + else: + calibre_web_version = (constants.STABLE_VERSION['version'].replace("b", " Beta") + ' - ' + + constants.NIGHTLY_VERSION[0].replace('%', '%%') + ' - ' + + constants.NIGHTLY_VERSION[1].replace('%', '%%')) + if getattr(sys, 'frozen', False): + calibre_web_version += " - Exe-Version" + elif constants.HOME_CONFIG: + calibre_web_version += " - pyPi" -def collect_stats(): - _VERSIONS['ebook converter'] = converter.get_calibre_version() - _VERSIONS['unrar'] = converter.get_unrar_version() - _VERSIONS['kepubify'] = converter.get_kepubify_version() + _VERSIONS = {'Calibre Web': calibre_web_version} + _VERSIONS.update(OrderedDict( + Python=sys.version, + Platform='{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()), + )) + _VERSIONS.update(uploader.get_magick_version()) + _VERSIONS['Unrar'] = converter.get_unrar_version() + _VERSIONS['Ebook converter'] = converter.get_calibre_version() + _VERSIONS['Kepubify'] = converter.get_kepubify_version() + _VERSIONS.update(sorted_modules) return _VERSIONS @@ -80,7 +78,7 @@ def collect_stats(): def stats(): counter = calibre_db.session.query(db.Books).count() authors = calibre_db.session.query(db.Authors).count() - categorys = calibre_db.session.query(db.Tags).count() + 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=categorys, 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 e487b5ca..fa29759e 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -22,17 +22,21 @@ import os import re -import base64 import json import operator -from datetime import datetime, timedelta, time +import time +import sys +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_babel import get_locale, format_time, format_datetime, format_timedelta from flask import session as flask_session from sqlalchemy import and_ from sqlalchemy.orm.attributes import flag_modified @@ -50,27 +54,28 @@ from .services.worker import WorkerThread from .babel import get_available_translations, get_available_locale, get_user_locale_language from . import debug_info - log = logger.create() feature_support = { - 'ldap': bool(services.ldap), - 'goodreads': bool(services.goodreads_support), - 'kobo': bool(services.kobo), - 'updater': constants.UPDATER_AVAILABLE, - 'gmail': bool(services.gmail), - 'scheduler': schedule.use_APScheduler, - 'gdrive': gdrive_support - } + 'ldap': bool(services.ldap), + 'goodreads': bool(services.goodreads_support), + 'kobo': bool(services.kobo), + 'updater': constants.UPDATER_AVAILABLE, + 'gmail': bool(services.gmail), + 'scheduler': schedule.use_APScheduler, + 'gdrive': gdrive_support +} try: import rarfile # pylint: disable=unused-import + feature_support['rar'] = True except (ImportError, SyntaxError): feature_support['rar'] = False try: from .oauth_bb import oauth_check, oauthblueprints + feature_support['oauth'] = True except ImportError as err: log.debug('Cannot import Flask-Dance, login with Oauth will not work: %s', err) @@ -78,7 +83,6 @@ except ImportError as err: oauthblueprints = [] oauth_check = {} - admi = Blueprint('admin', __name__) @@ -98,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'): @@ -134,31 +139,42 @@ def admin_forbidden(): @admin_required def shutdown(): task = request.get_json().get('parameter', -1) - showtext = {} + show_text = {} if task in (0, 1): # valid commandos received # close all database connections calibre_db.dispose() ub.dispose() if task == 0: - showtext['text'] = _(u'Server restarted, please reload page') + show_text['text'] = _('Server restarted, please reload page.') else: - showtext['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(showtext) + return json.dumps(show_text) if task == 2: log.warning("reconnecting to calibre database") calibre_db.reconnect_db(config, ub.app_DB_path) - showtext['text'] = _(u'Reconnect successful') - return json.dumps(showtext) + show_text['text'] = _('Success! Database Reconnected') + return json.dumps(show_text) + + show_text['text'] = _('Unknown command') + return json.dumps(show_text), 400 - showtext['text'] = _(u'Unknown command') - return json.dumps(showtext), 400 + +@admi.route("/metadata_backup", methods=["POST"]) +@login_required +@admin_required +def queue_metadata_backup(): + show_text = {} + log.warning("Queuing all books for metadata backup") + helper.set_all_metadata_dirty() + show_text['text'] = _('Success! Books queued for Metadata Backup, please check Tasks for result') + return json.dumps(show_text) -# method is available without login and not protected by CSRF to make it easy reachable, is per default switched of +# method is available without login and not protected by CSRF to make it easy reachable, is per default switched off # needed for docker applications, as changes on metadata.db from host are not visible to application @admi.route("/reconnect", methods=['GET']) def reconnect(): @@ -187,32 +203,32 @@ 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'] tz = timedelta(seconds=time.timezone if (time.localtime().tm_isdst == 0) else time.altzone) form_date = datetime.strptime(commit[:19], "%Y-%m-%dT%H:%M:%S") - if len(commit) > 19: # check if string has timezone + if len(commit) > 19: # check if string has timezone if commit[19] == '+': form_date -= timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) elif commit[19] == '-': form_date += timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) commit = format_datetime(form_date - tz, format='short') else: - commit = version['version'] + commit = version['version'].replace("b", " Beta") all_user = ub.session.query(ub.User).all() - email_settings = config.get_mail_settings() - schedule_time = format_time(time(hour=config.schedule_start_time), format="short") + # 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"]) @@ -232,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"]) @@ -260,9 +276,9 @@ def calibreweb_alive(): @login_required @admin_required def view_configuration(): - read_column = calibre_db.session.query(db.CustomColumns)\ + read_column = calibre_db.session.query(db.CustomColumns) \ .filter(and_(db.CustomColumns.datatype == 'bool', db.CustomColumns.mark_for_delete == 0)).all() - restrict_columns = calibre_db.session.query(db.CustomColumns)\ + restrict_columns = calibre_db.session.query(db.CustomColumns) \ .filter(and_(db.CustomColumns.datatype == 'text', db.CustomColumns.mark_for_delete == 0)).all() languages = calibre_db.speaking_language() translations = get_available_locale() @@ -270,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") @@ -281,11 +297,11 @@ def edit_user_table(): languages = calibre_db.speaking_language() translations = get_available_locale() all_user = ub.session.query(ub.User) - tags = calibre_db.session.query(db.Tags)\ - .join(db.books_tags_link)\ - .join(db.Books)\ + tags = calibre_db.session.query(db.Tags) \ + .join(db.books_tags_link) \ + .join(db.Books) \ .filter(calibre_db.common_filters()) \ - .group_by(text('books_tags_link.tag'))\ + .group_by(text('books_tags_link.tag')) \ .order_by(db.Tags.name).all() if config.config_restricted_column: custom_values = calibre_db.session.query(db.cc_classes[config.config_restricted_column]).all() @@ -304,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") @@ -462,20 +478,20 @@ def edit_list_user(param): elif param.endswith('role'): value = int(vals['field_index']) if user.name == "Guest" and value in \ - [constants.ROLE_ADMIN, constants.ROLE_PASSWD, constants.ROLE_EDIT_SHELFS]: + [constants.ROLE_ADMIN, constants.ROLE_PASSWD, constants.ROLE_EDIT_SHELFS]: raise Exception(_("Guest can't have this role")) # check for valid value, last on checks for power of 2 value - if value > 0 and value <= constants.ROLE_VIEWER and (value & value-1 == 0 or value == 1): + if value > 0 and value <= constants.ROLE_VIEWER and (value & value - 1 == 0 or value == 1): if vals['value'] == 'true': user.role |= value elif vals['value'] == 'false': if value == constants.ROLE_ADMIN: - if not ub.session.query(ub.User).\ - filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN, - ub.User.id != user.id).count(): + if not ub.session.query(ub.User). \ + filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN, + 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: @@ -487,7 +503,7 @@ def edit_list_user(param): if user.name == "Guest" and value == constants.SIDEBAR_READ_AND_UNREAD: raise Exception(_("Guest can't have this view")) # check for valid value, last on checks for power of 2 value - if value > 0 and value <= constants.SIDEBAR_LIST and (value & value-1 == 0 or value == 1): + if value > 0 and value <= constants.SIDEBAR_LIST and (value & value - 1 == 0 or value == 1): if vals['value'] == 'true': user.sidebar_view |= value elif vals['value'] == 'false': @@ -552,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") @@ -578,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() @@ -613,7 +629,8 @@ def load_dialogtexts(element_id): elif element_id == "db_submit": texts["main"] = _('Are you sure you want to change Calibre library location?') elif element_id == "admin_refresh_cover_cache": - texts["main"] = _('Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?') + texts["main"] = _('Calibre-Web will search for updated Covers ' + 'and update Cover Thumbnails, this may take a while?') elif element_id == "btnfullsync": texts["main"] = _("Are you sure you want delete Calibre-Web's sync database " "to force a full sync with your Kobo Reader?") @@ -639,7 +656,7 @@ def edit_domain(allow): @admin_required def add_domain(allow): domain_name = request.form.to_dict()['domainname'].replace('*', '%').replace('?', '_').lower() - check = ub.session.query(ub.Registration).filter(ub.Registration.domain == domain_name)\ + check = ub.session.query(ub.Registration).filter(ub.Registration.domain == domain_name) \ .filter(ub.Registration.allow == allow).first() if not check: new_domain = ub.Registration(domain=domain_name, allow=allow) @@ -744,6 +761,7 @@ def edit_restriction(res_type, user_id): ub.session_commit("Changed denied columns of user {} to {}".format(usr.name, usr.denied_column_value)) return "" + @admi.route("/ajax/addrestriction/", methods=['POST']) @login_required @admin_required @@ -856,16 +874,16 @@ def delete_restriction(res_type, user_id): @login_required @admin_required def list_restriction(res_type, user_id): - if res_type == 0: # Tags as template - restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd'+str(i)} + if res_type == 0: # Tags as template + restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd' + str(i)} for i, x in enumerate(config.list_denied_tags()) if x != ''] - allow = [{'Element': x, 'type': _('Allow'), 'id': 'a'+str(i)} + allow = [{'Element': x, 'type': _('Allow'), 'id': 'a' + str(i)} for i, x in enumerate(config.list_allowed_tags()) if x != ''] json_dumps = restrict + allow elif res_type == 1: # CustomC as template - restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd'+str(i)} + restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd' + str(i)} for i, x in enumerate(config.list_denied_column_values()) if x != ''] - allow = [{'Element': x, 'type': _('Allow'), 'id': 'a'+str(i)} + allow = [{'Element': x, 'type': _('Allow'), 'id': 'a' + str(i)} for i, x in enumerate(config.list_allowed_column_values()) if x != ''] json_dumps = restrict + allow elif res_type == 2: # Tags per user @@ -873,9 +891,9 @@ def list_restriction(res_type, user_id): usr = ub.session.query(ub.User).filter(ub.User.id == user_id).first() else: usr = current_user - restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd'+str(i)} + restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd' + str(i)} for i, x in enumerate(usr.list_denied_tags()) if x != ''] - allow = [{'Element': x, 'type': _('Allow'), 'id': 'a'+str(i)} + allow = [{'Element': x, 'type': _('Allow'), 'id': 'a' + str(i)} for i, x in enumerate(usr.list_allowed_tags()) if x != ''] json_dumps = restrict + allow elif res_type == 3: # CustomC per user @@ -883,9 +901,9 @@ def list_restriction(res_type, user_id): usr = ub.session.query(ub.User).filter(ub.User.id == user_id).first() else: usr = current_user - restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd'+str(i)} + restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd' + str(i)} for i, x in enumerate(usr.list_denied_column_values()) if x != ''] - allow = [{'Element': x, 'type': _('Allow'), 'id': 'a'+str(i)} + allow = [{'Element': x, 'type': _('Allow'), 'id': 'a' + str(i)} for i, x in enumerate(usr.list_allowed_column_values()) if x != ''] json_dumps = restrict + allow else: @@ -915,7 +933,7 @@ def ajax_pathchooser(): def check_valid_read_column(column): if column != "0": if not calibre_db.session.query(db.CustomColumns).filter(db.CustomColumns.id == column) \ - .filter(and_(db.CustomColumns.datatype == 'bool', db.CustomColumns.mark_for_delete == 0)).all(): + .filter(and_(db.CustomColumns.datatype == 'bool', db.CustomColumns.mark_for_delete == 0)).all(): return False return True @@ -923,7 +941,7 @@ def check_valid_read_column(column): def check_valid_restricted_column(column): if column != "0": if not calibre_db.session.query(db.CustomColumns).filter(db.CustomColumns.id == column) \ - .filter(and_(db.CustomColumns.datatype == 'text', db.CustomColumns.mark_for_delete == 0)).all(): + .filter(and_(db.CustomColumns.datatype == 'text', db.CustomColumns.mark_for_delete == 0)).all(): return False return True @@ -951,7 +969,7 @@ def prepare_tags(user, action, tags_name, id_list): raise Exception(_("Tag not found")) new_tags_list = [x.name for x in tags] else: - tags = calibre_db.session.query(db.cc_classes[config.config_restricted_column])\ + tags = calibre_db.session.query(db.cc_classes[config.config_restricted_column]) \ .filter(db.cc_classes[config.config_restricted_column].id.in_(id_list)).all() new_tags_list = [x.value for x in tags] saved_tags_list = user.__dict__[tags_name].split(",") if len(user.__dict__[tags_name]) else [] @@ -964,6 +982,19 @@ def prepare_tags(user, action, tags_name, id_list): return ",".join(saved_tags_list) +def get_drives(current): + drive_letters = [] + for d in string.ascii_uppercase: + if os.path.exists('{}:'.format(d)) and current[0].lower() != d.lower(): + drive = "{}:\\".format(d) + data = {"name": drive, "fullpath": drive} + data["sort"] = "_" + data["fullpath"].lower() + data["type"] = "dir" + data["size"] = "" + drive_letters.append(data) + return drive_letters + + def pathchooser(): browse_for = "folder" folder_only = request.args.get('folder', False) == "true" @@ -971,43 +1002,45 @@ def pathchooser(): path = os.path.normpath(request.args.get('path', "")) if os.path.isfile(path): - oldfile = path + old_file = path path = os.path.dirname(path) else: - oldfile = "" + old_file = "" absolute = False if os.path.isdir(path): - # if os.path.isabs(path): cwd = os.path.realpath(path) absolute = True - # else: - # cwd = os.path.relpath(path) else: cwd = os.getcwd() cwd = os.path.normpath(os.path.realpath(cwd)) - parentdir = os.path.dirname(cwd) + parent_dir = os.path.dirname(cwd) if not absolute: if os.path.realpath(cwd) == os.path.realpath("/"): cwd = os.path.relpath(cwd) else: cwd = os.path.relpath(cwd) + os.path.sep - parentdir = os.path.relpath(parentdir) + os.path.sep + parent_dir = os.path.relpath(parent_dir) + os.path.sep - if os.path.realpath(cwd) == os.path.realpath("/"): - parentdir = "" + files = [] + if os.path.realpath(cwd) == os.path.realpath("/") \ + or (sys.platform == "win32" and os.path.realpath(cwd)[1:] == os.path.realpath("/")[1:]): + # we are in root + parent_dir = "" + if sys.platform == "win32": + files = get_drives(cwd) try: folders = os.listdir(cwd) except Exception: folders = [] - files = [] 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 @@ -1037,9 +1070,9 @@ def pathchooser(): context = { "cwd": cwd, "files": files, - "parentdir": parentdir, + "parentdir": parent_dir, "type": browse_for, - "oldfile": oldfile, + "oldfile": old_file, "absolute": absolute, } return json.dumps(context) @@ -1058,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): @@ -1077,12 +1110,12 @@ def _configuration_gdrive_helper(to_save): if not gdrive_secrets: return _configuration_result(_('client_secrets.json Is Not Configured For Web Application')) gdriveutils.update_settings( - gdrive_secrets['client_id'], - gdrive_secrets['client_secret'], - gdrive_secrets['redirect_uris'][0] - ) + gdrive_secrets['client_id'], + gdrive_secrets['client_secret'], + gdrive_secrets['redirect_uris'][0] + ) - # always show google drive settings, but in case of error deny support + # always show Google Drive settings, but in case of error deny support new_gdrive_value = (not gdrive_error) and ("config_use_google_drive" in to_save) if config.config_use_google_drive and not new_gdrive_value: config.config_google_drive_watch_changes_response = {} @@ -1097,12 +1130,12 @@ def _configuration_oauth_helper(to_save): reboot_required = False for element in oauthblueprints: if to_save["config_" + str(element['id']) + "_oauth_client_id"] != element['oauth_client_id'] \ - or to_save["config_" + str(element['id']) + "_oauth_client_secret"] != element['oauth_client_secret']: + or to_save["config_" + str(element['id']) + "_oauth_client_secret"] != element['oauth_client_secret']: reboot_required = True element['oauth_client_id'] = to_save["config_" + str(element['id']) + "_oauth_client_id"] element['oauth_client_secret'] = to_save["config_" + str(element['id']) + "_oauth_client_secret"] if to_save["config_" + str(element['id']) + "_oauth_client_id"] \ - and to_save["config_" + str(element['id']) + "_oauth_client_secret"]: + and to_save["config_" + str(element['id']) + "_oauth_client_secret"]: active_oauths += 1 element["active"] = 1 else: @@ -1132,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") @@ -1147,21 +1179,26 @@ def _configuration_ldap_helper(to_save): reboot_required |= _config_string(to_save, "config_ldap_cert_path") reboot_required |= _config_string(to_save, "config_ldap_key_path") _config_string(to_save, "config_ldap_group_name") - 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 \ or not config.config_ldap_port \ or not config.config_ldap_dn \ - or not config.config_ldap_user_object: + or not config.config_ldap_user_object: return reboot_required, _configuration_result(_('Please Enter a LDAP Provider, ' 'Port, DN and User Object Identifier')) 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: @@ -1225,16 +1262,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) @@ -1253,40 +1290,44 @@ 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) return edit_mailsettings() else: - _config_string(to_save, "mail_server") _config_int(to_save, "mail_port") _config_int(to_save, "mail_use_ssl") - _config_string(to_save, "mail_login") - _config_string(to_save, "mail_password") - _config_string(to_save, "mail_from") - _config_int(to_save, "mail_size", lambda y: int(y)*1024*1024) + 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() + config.mail_login = to_save.get('mail_login', "").strip() try: config.save() 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(_("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() @@ -1300,16 +1341,16 @@ def edit_scheduledtasks(): duration_field = list() for n in range(24): - time_field.append((n , format_time(time(hour=n), format="short",))) + time_field.append((n, format_time(datetime_time(hour=n), format="short", ))) for n in range(5, 65, 5): t = timedelta(hours=n // 60, minutes=n % 60) - duration_field.append((n, format_timedelta(t, threshold=.9))) + duration_field.append((n, format_timedelta(t, threshold=.97))) return render_title_template("schedule_edit.html", 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"]) @@ -1319,23 +1360,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() @@ -1345,7 +1387,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") @@ -1360,7 +1402,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() @@ -1379,7 +1421,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") @@ -1390,14 +1432,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')) @@ -1408,7 +1450,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, @@ -1458,7 +1500,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 '' @@ -1519,11 +1561,11 @@ def ldap_import_create_user(user, user_data): log.warning("LDAP User %s Already in Database", user_data) return 0, None - kindlemail = '' + ereader_mail = '' if 'mail' in user_data: useremail = user_data['mail'][0].decode('utf-8') if len(user_data['mail']) > 1: - kindlemail = user_data['mail'][1].decode('utf-8') + ereader_mail = user_data['mail'][1].decode('utf-8') else: log.debug('No Mail Field Found in LDAP Response') @@ -1539,7 +1581,7 @@ def ldap_import_create_user(user, user_data): content.name = username content.password = '' # dummy password which will be replaced by ldap one content.email = useremail - content.kindle_mail = kindlemail + content.kindle_mail = ereader_mail content.default_language = config.config_default_language content.locale = config.config_default_locale content.role = config.config_default_role @@ -1551,7 +1593,7 @@ def ldap_import_create_user(user, user_data): ub.session.add(content) try: ub.session.commit() - return 1, None # increase no of users + return 1, None # increase no of users except Exception as ex: log.warning("Failed to create LDAP user: %s - %s", user, ex) ub.session.rollback() @@ -1653,7 +1695,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): @@ -1663,10 +1705,11 @@ def _db_configuration_update_helper(): return _db_configuration_result('{}'.format(ex), gdrive_error) if db_change or not db_valid or not config.db_configured \ - or config.config_calibre_dir != to_save["config_calibre_dir"]: - if not calibre_db.setup_db(to_save['config_calibre_dir'], ub.app_DB_path): - return _db_configuration_result(_('DB Location is not Valid, Please Enter Correct Path'), - gdrive_error) + or config.config_calibre_dir != to_save["config_calibre_dir"]: + if not os.path.exists(metadata_db) or not to_save['config_calibre_dir']: + return _db_configuration_result(_('DB Location is not Valid, Please Enter Correct Path'), gdrive_error) + else: + calibre_db.setup_db(to_save['config_calibre_dir'], ub.app_DB_path) config.store_calibre_uuid(calibre_db, db.Library_Id) # if db changed -> delete shelfs, delete download books, delete read books, kobo sync... if db_change: @@ -1684,7 +1727,10 @@ 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_string(to_save, "config_calibre_split_dir") + config.config_calibre_split = to_save.get('config_calibre_split', 0) == "on" + calibre_db.update_config(config) config.save() return _db_configuration_result(None, gdrive_error) @@ -1705,6 +1751,7 @@ def _configuration_update_helper(): _config_checkbox_int(to_save, "config_uploading") _config_checkbox_int(to_save, "config_unicode_filename") + _config_checkbox_int(to_save, "config_embed_metadata") # Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case reboot_required |= (_config_checkbox_int(to_save, "config_anonbrowse") and config.config_login_type == constants.LOGIN_LDAP) @@ -1747,10 +1794,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") @@ -1763,10 +1811,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: @@ -1776,7 +1839,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: @@ -1792,7 +1855,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') @@ -1823,7 +1886,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): @@ -1835,25 +1898,25 @@ 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 User name, if not existing, change + # Query username, if not existing, change content.name = check_username(to_save["name"]) if to_save.get("kindle_mail"): 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 @@ -1864,17 +1927,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): @@ -1902,10 +1965,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")) @@ -1923,14 +1986,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() @@ -1958,9 +2013,21 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support): if to_save.get("locale"): content.locale = to_save["locale"] try: - if to_save.get("email", content.email) != content.email: - content.email = check_email(to_save["email"]) - # Query User name, if not existing, change + 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(_("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 if to_save.get("name", content.name) != content.name: if to_save.get("name") == "Guest": raise Exception(_("Guest Name can't be changed")) @@ -1979,24 +2046,24 @@ 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 "" def extract_user_data_from_field(user, field): - match = re.search(field + r"=([\.\d\s\w-]+)", user, re.IGNORECASE | re.UNICODE) + match = re.search(field + r"=([@\.\d\s\w-]+)", user, re.IGNORECASE | re.UNICODE) if match: return match.group(1) else: diff --git a/cps/babel.py b/cps/babel.py index f5ecaf5a..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: @@ -32,8 +31,10 @@ def get_locale(): def get_user_locale_language(user_language): return Locale.parse(user_language).get_language_name(get_locale()) + def get_available_locale(): return [Locale('en')] + babel.list_translations() + def get_available_translations(): return set(str(item) for item in get_available_locale()) diff --git a/cps/cache_buster.py b/cps/cache_buster.py index ba19afd6..eb6b7433 100644 --- a/cps/cache_buster.py +++ b/cps/cache_buster.py @@ -49,7 +49,7 @@ def init_cache_busting(app): rooted_filename = os.path.join(dirpath, filename) try: with open(rooted_filename, 'rb') as f: - file_hash = hashlib.md5(f.read()).hexdigest()[:7] # nosec + file_hash = hashlib.md5(f.read()).hexdigest()[:7] # nosec # save version to tables file_path = rooted_filename.replace(static_folder, "") file_path = file_path.replace("\\", "/") # Convert Windows path to web path @@ -59,11 +59,11 @@ def init_cache_busting(app): log.debug('Finished computing cache-busting values') - def bust_filename(filename): - return hash_table.get(filename, "") + def bust_filename(file_name): + return hash_table.get(file_name, "") - def unbust_filename(filename): - return filename.split("?", 1)[0] + def unbust_filename(file_name): + return file_name.split("?", 1)[0] @app.url_defaults # pylint: disable=unused-variable diff --git a/cps/cli.py b/cps/cli.py index cf4f36fb..855ad899 100644 --- a/cps/cli.py +++ b/cps/cli.py @@ -26,10 +26,12 @@ from .constants import STABLE_VERSION as _STABLE_VERSION from .constants import NIGHTLY_VERSION as _NIGHTLY_VERSION from .constants import DEFAULT_SETTINGS_FILE, DEFAULT_GDRIVE_FILE + def version_info(): if _NIGHTLY_VERSION[1].startswith('$Format'): - return "Calibre-Web version: %s - unkown git-clone" % _STABLE_VERSION['version'] - return "Calibre-Web version: %s -%s" % (_STABLE_VERSION['version'], _NIGHTLY_VERSION[1]) + return "Calibre-Web version: %s - unknown git-clone" % _STABLE_VERSION['version'].replace("b", " Beta") + return "Calibre-Web version: %s -%s" % (_STABLE_VERSION['version'].replace("b", " Beta"), _NIGHTLY_VERSION[1]) + class CliParameter(object): @@ -37,15 +39,16 @@ class CliParameter(object): self.arg_parser() def arg_parser(self): - parser = argparse.ArgumentParser(description='Calibre Web is a web app' - ' providing a interface for browsing, reading and downloading eBooks\n', + parser = argparse.ArgumentParser(description='Calibre Web is a web app providing ' + 'a interface for browsing, reading and downloading eBooks\n', prog='cps.py') parser.add_argument('-p', metavar='path', help='path and name to settings db, e.g. /opt/cw.db') parser.add_argument('-g', metavar='path', help='path and name to gdrive db, e.g. /opt/gd.db') - parser.add_argument('-c', metavar='path', - help='path and name to SSL certfile, e.g. /opt/test.cert, 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('-c', metavar='path', help='path and name to SSL certfile, e.g. /opt/test.cert, ' + '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') @@ -58,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) @@ -67,7 +71,6 @@ class CliParameter(object): if os.path.isdir(self.gd_path): self.gd_path = os.path.join(self.gd_path, DEFAULT_GDRIVE_FILE) - # handle and check parameter for ssl encryption self.certfilepath = None self.keyfilepath = None @@ -96,7 +99,7 @@ class CliParameter(object): self.keyfilepath = "" # dry run updater - self.dry_run =args.d or None + self.dry_run = args.d or None # enable reconnect endpoint for docker database reconnect self.reconnect_enable = args.r or os.environ.get("CALIBRE_RECONNECT", None) # load covers from localhost @@ -112,7 +115,7 @@ class CliParameter(object): else: socket.inet_pton(socket.AF_INET, self.ip_address) else: - # on windows python < 3.4, inet_pton is not available + # on Windows python < 3.4, inet_pton is not available # inet_atom only handles IPv4 addresses socket.inet_aton(self.ip_address) except socket.error as err: 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 9b8c29fa..565dec87 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 @@ -36,6 +40,7 @@ from .subproc_wrapper import process_wait log = logger.create() _Base = declarative_base() + class _Flask_Settings(_Base): __tablename__ = 'flask_settings' @@ -56,7 +61,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) @@ -64,24 +70,25 @@ class _Settings(_Base): config_calibre_dir = Column(String) config_calibre_uuid = Column(String) + config_calibre_split = Column(Boolean, default=False) + config_calibre_split_dir = Column(String) config_port = Column(Integer, default=constants.DEFAULT_PORT) config_external_port = Column(Integer, default=constants.DEFAULT_PORT) config_certfile = Column(String) config_keyfile = Column(String) - config_trustedhosts = Column(String,default='') - config_calibre_web_title = Column(String, default=u'Calibre-Web') + config_trustedhosts = Column(String, default='') + 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 +114,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,14 +125,15 @@ 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="") config_ldap_key_path = Column(String, default="") config_ldap_dn = Column(String, default='dc=example,dc=org') config_ldap_user_object = Column(String, default='uid=%s') - config_ldap_member_user_object = Column(String, default='') # + config_ldap_member_user_object = Column(String, default='') config_ldap_openldap = Column(Boolean, default=True) config_ldap_group_object_filter = Column(String, default='(&(objectclass=posixGroup)(cn=%s))') config_ldap_group_members_field = Column(String, default='memberUid') @@ -137,6 +146,7 @@ class _Settings(_Base): config_rarfile_location = Column(String, default=None) config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) config_unicode_filename = Column(Boolean, default=False) + config_embed_metadata = Column(Boolean, default=True) config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE) @@ -148,24 +158,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 @@ -260,14 +281,14 @@ class _ConfigSQL(object): return logger.get_level_name(self.config_log_level) def get_mail_settings(self): - return {k:v for k, v in self.__dict__.items() if k.startswith('mail_')} + return {k: v for k, v in self.__dict__.items() if k.startswith('mail_')} def get_mail_server_configured(self): return bool((self.mail_server != constants.DEFAULT_MAIL_SERVER and self.mail_server_type == 0) or (self.mail_gmail_token != {} and self.mail_server_type == 1)) def get_scheduled_task_settings(self): - return {k:v for k, v in self.__dict__.items() if k.startswith('schedule_')} + return {k: v for k, v in self.__dict__.items() if k.startswith('schedule_')} def set_from_dictionary(self, dictionary, field, convertor=None, default=None, encode=None): """Possibly updates a field of this object. @@ -296,15 +317,15 @@ 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 def load(self): - '''Load all configuration values from the underlying storage.''' + """Load all configuration values from the underlying storage.""" s = self._read_from_storage() # type: _Settings for k, v in s.__dict__.items(): if k[0] != '_': @@ -313,7 +334,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: @@ -321,30 +348,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.''' + """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) @@ -360,9 +394,11 @@ class _ConfigSQL(object): log.error(error) log.warning("invalidating configuration") self.db_configured = False - # self.config_calibre_dir = None self.save() + def get_book_path(self): + return self.config_calibre_split_dir if self.config_calibre_split_dir else self.config_calibre_dir + def store_calibre_uuid(self, calibre_db, Library_table): try: calibre_uuid = calibre_db.session.query(Library_table).one_or_none() @@ -372,7 +408,40 @@ class _ConfigSQL(object): except AttributeError: pass -def _migrate_table(session, orm_class): + def __setattr__(self, attr_name, attr_value): + super().__setattr__(attr_name, attr_value) + self.__dict__["dirty"].append(attr_name) + + +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(): @@ -393,9 +462,9 @@ def _migrate_table(session, orm_class): else: column_type = column.type alter_table = text("ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__, - column_name, - column_type, - column_default)) + column_name, + column_type, + column_default)) log.debug(alter_table) session.execute(alter_table) changed = True @@ -463,22 +532,20 @@ 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): @@ -488,3 +555,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 b613d0aa..ef207e02 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'} @@ -168,13 +173,12 @@ 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 Beta'} +# python build process likes to have x.y.zbw -> b for beta and w a counting number +STABLE_VERSION = {'version': '0.6.22b'} NIGHTLY_VERSION = dict() NIGHTLY_VERSION[0] = '$Format:%H$' NIGHTLY_VERSION[1] = '$Format:%cI$' -# NIGHTLY_VERSION[0] = 'bb7d2c6273ae4560e83950d36d64533343623a57' -# NIGHTLY_VERSION[1] = '2018-09-09T10:13:08+02:00' # CACHE CACHE_TYPE_THUMBNAILS = 'thumbnails' diff --git a/cps/converter.py b/cps/converter.py index af2a6c09..981b3909 100644 --- a/cps/converter.py +++ b/cps/converter.py @@ -54,10 +54,9 @@ def get_calibre_version(): def get_unrar_version(): unrar_version = _get_command_version(config.config_rarfile_location, r'UNRAR.*\d') if unrar_version == "not installed": - unrar_version = _get_command_version(config.config_rarfile_location, r'unrar.*\d','-V') + unrar_version = _get_command_version(config.config_rarfile_location, r'unrar.*\d', '-V') return unrar_version -def get_kepubify_version(): - return _get_command_version(config.config_kepubifypath, r'kepubify\s','--version') - +def get_kepubify_version(): + return _get_command_version(config.config_kepubifypath, r'kepubify\s', '--version') diff --git a/cps/db.py b/cps/db.py index f4dc4ccb..ceb692ec 100644 --- a/cps/db.py +++ b/cps/db.py @@ -19,7 +19,6 @@ import os import re -import ast import json from datetime import datetime from urllib.parse import quote @@ -112,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): @@ -189,7 +195,7 @@ class Comments(Base): return self.text def __repr__(self): - return u"".format(self.text) + return "".format(self.text) class Tags(Base): @@ -204,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): @@ -216,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 @@ -224,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): @@ -242,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): @@ -258,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): @@ -272,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): @@ -295,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): @@ -320,7 +344,16 @@ 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): + __tablename__ = 'metadata_dirtied' + id = Column(Integer, primary_key=True, autoincrement=True) + book = Column(Integer, ForeignKey('books.id'), nullable=False, unique=True) + + def __init__(self, book): + self.book = book class Books(Base): @@ -365,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) @@ -388,9 +421,36 @@ class CustomColumns(Base): normalized = Column(Boolean) def get_display_dict(self): - display_dict = ast.literal_eval(self.display) + display_dict = json.loads(self.display) return display_dict + def to_json(self, value, extra, sequence): + content = dict() + content['table'] = "custom_column_" + str(self.id) + content['column'] = "value" + content['datatype'] = self.datatype + content['is_multiple'] = None if not self.is_multiple else "|" + content['kind'] = "field" + content['name'] = self.name + content['search_terms'] = ['#' + self.label] + content['label'] = self.label + content['colnum'] = self.id + content['display'] = self.get_display_dict() + content['is_custom'] = True + content['is_category'] = self.datatype in ['text', 'rating', 'enumeration', 'series'] + content['link_column'] = "value" + content['category_sort'] = "value" + content['is_csp'] = False + content['is_editable'] = self.editable + content['rec_index'] = sequence + 22 # toDo why ?? + 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'] = {} if not self.is_multiple else {"cache_to_list": "|", "ui_to_list": ",", "list_to_ui": ", "} + return json.dumps(content, ensure_ascii=False) + class AlchemyEncoder(json.JSONEncoder): @@ -568,12 +628,12 @@ class CalibreDB: if not config_calibre_dir: cls.config.invalidate() - return False + return None dbpath = os.path.join(config_calibre_dir, "metadata.db") if not os.path.exists(dbpath): cls.config.invalidate() - return False + return None try: cls.engine = create_engine('sqlite://', @@ -589,7 +649,7 @@ class CalibreDB: # conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302 except Exception as ex: cls.config.invalidate(ex) - return False + return None cls.config.db_configured = True @@ -599,16 +659,15 @@ class CalibreDB: cls.setup_db_cc_classes(cc) except OperationalError as e: log.error_or_exception(e) - return False + return None 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() cls._init = True - return True def get_book(self, book_id): return self.session.query(Books).filter(Books.id == book_id).first() @@ -629,7 +688,7 @@ class CalibreDB: .join(read_column, read_column.book == book_id, isouter=True)) except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(read_column)) # Skip linking read column and return None instead of read status bd = self.session.query(Books, None, ub.ArchivedBook.is_archived) return (bd.filter(Books.id == book_id) @@ -643,6 +702,18 @@ class CalibreDB: def get_book_format(self, book_id, file_format): return self.session.query(Data).filter(Data.book == book_id).filter(Data.format == file_format).first() + def set_metadata_dirty(self, book_id): + if not self.session.query(Metadata_Dirtied).filter(Metadata_Dirtied.book == book_id).one_or_none(): + self.session.add(Metadata_Dirtied(book_id)) + + def delete_dirty_metadata(self, book_id): + try: + self.session.query(Metadata_Dirtied).filter(Metadata_Dirtied.book == book_id).delete() + self.session.commit() + except (OperationalError) as e: + self.session.rollback() + log.error("Database error: {}".format(e)) + # Language and content filters for displaying in the UI def common_filters(self, allow_show_archived=False, return_all_languages=False): if not allow_show_archived: @@ -676,9 +747,9 @@ class CalibreDB: except (KeyError, AttributeError, IndexError): pos_content_cc_filter = false() neg_content_cc_filter = true() - log.error("Custom Column No.{} is not existing in calibre database".format( + log.error("Custom Column No.{} does not exist in calibre database".format( self.config.config_restricted_column)) - flash(_("Custom Column No.%(column)d is not existing in calibre database", + flash(_("Custom Column No.%(column)d does not exist in calibre database", column=self.config.config_restricted_column), category="error") @@ -701,7 +772,7 @@ class CalibreDB: .select_from(Books) .outerjoin(read_column, read_column.book == Books.id)) except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(config_read_column)) # Skip linking read column and return None instead of read status query = self.session.query(database, None, ub.ArchivedBook.is_archived) return query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, @@ -779,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('&') @@ -945,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 dd5e858e..82ca8ca6 100644 --- a/cps/debug_info.py +++ b/cps/debug_info.py @@ -22,6 +22,7 @@ import glob import zipfile import json from io import BytesIO +from flask_babel.speaklater import LazyString import os @@ -32,6 +33,13 @@ from .about import collect_stats log = logger.create() +class lazyEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, LazyString): + return str(obj) + # Let the base class default method raise the TypeError + return json.JSONEncoder.default(self, obj) + def assemble_logfiles(file_name): log_list = sorted(glob.glob(file_name + '*'), reverse=True) wfd = BytesIO() @@ -57,8 +65,8 @@ 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())) - zf.writestr('libs.txt', json.dumps(collect_stats())) + 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)) memory_zip.seek(0) diff --git a/cps/dep_check.py b/cps/dep_check.py index 929185c2..34d0e24b 100644 --- a/cps/dep_check.py +++ b/cps/dep_check.py @@ -20,7 +20,8 @@ if not importlib: except ImportError as e: pkgresources = False -def load_dependencys(optional=False): + +def load_dependencies(optional=False): deps = list() if getattr(sys, 'frozen', False): pip_installed = os.path.join(BASE_DIR, ".pip_installed") @@ -41,7 +42,7 @@ def load_dependencys(optional=False): res = re.match(r'(.*?)([<=>\s]+)([\d\.]+),?\s?([<=>\s]+)?([\d\.]+)?', line.strip()) try: if getattr(sys, 'frozen', False): - dep_version = exe_deps[res.group(1).lower().replace('_','-')] + dep_version = exe_deps[res.group(1).lower().replace('_', '-')] else: if importlib: dep_version = version(res.group(1)) @@ -57,38 +58,38 @@ def load_dependencys(optional=False): def dependency_check(optional=False): d = list() - deps = load_dependencys(optional) + 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: - high_check = None + high_check = [] except ValueError: d.append({'name': dep[1], - 'target': "available", - 'found': "Not available" - }) + 'target': "available", + 'found': "Not available" + }) continue if dep[2].strip() == "==": if dep_version_int != low_check: d.append({'name': dep[1], - 'found': dep[0], - "target": dep[2] + dep[3]}) + 'found': dep[0], + "target": dep[2] + dep[3]}) continue elif dep[2].strip() == ">=": if dep_version_int < low_check: d.append({'name': dep[1], - 'found': dep[0], - "target": dep[2] + dep[3]}) + 'found': dep[0], + "target": dep[2] + dep[3]}) continue elif dep[2].strip() == ">": if dep_version_int <= low_check: d.append({'name': dep[1], - 'found': dep[0], - "target": dep[2] + dep[3]}) + 'found': dep[0], + "target": dep[2] + dep[3]}) continue if dep[4] and dep[5]: if dep[4].strip() == "<": diff --git a/cps/editbooks.py b/cps/editbooks.py old mode 100755 new mode 100644 index d3615050..4d195eb7 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -25,20 +25,33 @@ 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 +from lxml.etree import ParserError try: - from lxml.html.clean import clean_html + # at least bleach 6.0 is needed -> incomplatible change from list arguments to set arguments + 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 +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 @@ -106,7 +119,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")) @@ -124,7 +137,7 @@ def edit_book(book_id): edited_books_id = book.id modify_date = True title_author_error = helper.update_dir_structure(edited_books_id, - config.config_calibre_dir, + config.get_book_path(), input_authors[0], renamed_author=renamed) if title_author_error: @@ -150,7 +163,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: @@ -202,6 +215,7 @@ def edit_book(book_id): if modify_date: book.last_modified = datetime.utcnow() kobo_sync_status.remove_synced_book(edited_books_id, all=True) + calibre_db.set_metadata_dirty(book.id) calibre_db.session.merge(book) calibre_db.session.commit() @@ -221,10 +235,10 @@ def edit_book(book_id): calibre_db.session.rollback() flash(str(e), category="error") return redirect(url_for('web.show_book', book_id=book.id)) - except (OperationalError, IntegrityError) as e: + 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) @@ -268,7 +282,7 @@ def upload(): meta.extension.lower()) else: error = helper.update_dir_structure(book_id, - config.config_calibre_dir, + config.get_book_path(), input_authors[0], meta.file_path, title_dir + meta.extension.lower(), @@ -276,6 +290,8 @@ def upload(): move_coverfile(meta, db_book) + if modify_date: + calibre_db.set_metadata_dirty(book_id) # save data to database, reread data calibre_db.session.commit() @@ -284,7 +300,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) @@ -295,10 +311,11 @@ def upload(): else: resp = {"location": url_for('web.show_book', book_id=book_id)} return Response(json.dumps(resp), mimetype='application/json') - except (OperationalError, IntegrityError) as e: + 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') @@ -311,19 +328,19 @@ 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) - rtn = helper.convert_book_format(book_id, config.config_calibre_dir, book_format_from.upper(), + rtn = helper.convert_book_format(book_id, config.get_book_path(), book_format_from.upper(), 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)) @@ -385,7 +402,7 @@ def edit_list_book(param): elif param == 'title': sort_param = book.sort if handle_title_on_edit(book, vals.get('value', "")): - rename_error = helper.update_dir_structure(book.id, config.config_calibre_dir) + rename_error = helper.update_dir_structure(book.id, config.get_book_path()) if not rename_error: ret = Response(json.dumps({'success': True, 'newValue': book.title}), mimetype='application/json') @@ -403,7 +420,7 @@ def edit_list_book(param): mimetype='application/json') elif param == 'authors': input_authors, __, renamed = handle_author_on_edit(book, vals['value'], vals.get('checkA', None) == "true") - rename_error = helper.update_dir_structure(book.id, config.config_calibre_dir, input_authors[0], + rename_error = helper.update_dir_structure(book.id, config.get_book_path(), input_authors[0], renamed_author=renamed) if not rename_error: ret = Response(json.dumps({ @@ -443,11 +460,11 @@ def edit_list_book(param): if param == 'title' and vals.get('checkT') == "false": book.sort = sort_param calibre_db.session.commit() - except (OperationalError, IntegrityError) as e: + except (OperationalError, IntegrityError, StaleDataError) as e: 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 @@ -465,7 +482,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 "" @@ -507,10 +524,10 @@ def merge_list_book(): for element in from_book.data: if element.format not in to_file: # create new data entry with: book_id, book_format, uncompressed_size, name - filepath_new = os.path.normpath(os.path.join(config.config_calibre_dir, + filepath_new = os.path.normpath(os.path.join(config.get_book_path(), to_book.path, to_name + "." + element.format.lower())) - filepath_old = os.path.normpath(os.path.join(config.config_calibre_dir, + filepath_old = os.path.normpath(os.path.join(config.get_book_path(), from_book.path, element.name + "." + element.format.lower())) copyfile(filepath_old, filepath_new) @@ -550,15 +567,16 @@ def table_xchange_author_title(): if edited_books_id: # toDo: Handle error - edit_error = helper.update_dir_structure(edited_books_id, config.config_calibre_dir, input_authors[0], + edit_error = helper.update_dir_structure(edited_books_id, config.get_book_path(), input_authors[0], renamed_author=renamed) if modify_date: book.last_modified = datetime.utcnow() + calibre_db.set_metadata_dirty(book.id) try: calibre_db.session.commit() - except (OperationalError, IntegrityError) as e: + 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: @@ -568,9 +586,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'), @@ -592,6 +610,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 @@ -606,7 +626,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: @@ -623,11 +643,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) @@ -682,7 +702,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) @@ -732,7 +752,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 @@ -744,7 +764,7 @@ def move_coverfile(meta, db_book): cover_file = meta.cover else: cover_file = os.path.join(constants.STATIC_DIR, 'generic_cover.jpg') - new_cover_path = os.path.join(config.config_calibre_dir, db_book.path) + new_cover_path = os.path.join(config.get_book_path(), db_book.path) try: os.makedirs(new_cover_path, exist_ok=True) copyfile(cover_file, os.path.join(new_cover_path, "cover.jpg")) @@ -752,7 +772,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") @@ -766,7 +786,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') @@ -830,7 +850,7 @@ def delete_book_from_table(book_id, book_format, json_response): book = calibre_db.get_book(book_id) if book: try: - result, error = helper.delete_book(book, config.config_calibre_dir, book_format=book_format.upper()) + result, error = helper.delete_book(book, config.get_book_path(), book_format=book_format.upper()) if not result: if json_response: return json.dumps([{"location": url_for("edit-book.show_edit_book", book_id=book_id), @@ -887,7 +907,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")) @@ -922,7 +942,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) @@ -983,7 +1003,14 @@ def edit_book_series_index(series_index, book): def edit_book_comments(comments, book): modify_date = False if comments: - comments = clean_html(comments) + try: + if BLEACH: + comments = clean_html(comments, tags=set(), attributes=set()) + else: + comments = clean_html(comments) + except ParserError as e: + log.error("Comments of book {} are corrupted: {}".format(book.id, e)) + comments = "" if len(book.comments): if book.comments[0].text != comments: book.comments[0].text = comments @@ -1007,7 +1034,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 @@ -1118,9 +1145,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 @@ -1149,7 +1177,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() @@ -1162,7 +1190,7 @@ def upload_single_file(file_request, book, book_id): return False file_name = book.path.rsplit('/', 1)[-1] - filepath = os.path.normpath(os.path.join(config.config_calibre_dir, book.path)) + filepath = os.path.normpath(os.path.join(config.get_book_path(), book.path)) saved_filename = os.path.join(filepath, file_name + '.' + file_ext) # check if file path exists, otherwise create it, copy file to calibre path and delete temp file @@ -1170,12 +1198,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) @@ -1190,20 +1218,21 @@ def upload_single_file(file_request, book, book_id): calibre_db.session.add(db_format) calibre_db.session.commit() calibre_db.update_title_sort(config) - except (OperationalError, IntegrityError) as e: + 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 @@ -1213,7 +1242,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: @@ -1237,18 +1266,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)) @@ -1256,6 +1285,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 @@ -1263,14 +1295,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 @@ -1284,13 +1317,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: @@ -1306,6 +1337,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 @@ -1319,27 +1351,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 @@ -1374,13 +1413,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 d358d038..a45fb926 100644 --- a/cps/epub.py +++ b/cps/epub.py @@ -21,25 +21,47 @@ import zipfile from lxml import etree from . import isoLanguages, cover +from . import config, logger from .helper import split_authors +from .epub_helper import get_content_opf, default_ns 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): + file_path = os.path.normpath(os.path.join(config.get_book_path(), + book.path, book_data.name + "." + book_data.format.lower())) + + try: + tree, __ = get_content_opf(file_path, default_ns) + p = tree.xpath('/pkg:package/pkg:metadata', namespaces=default_ns)[0] + + layout = p.xpath('pkg:meta[@property="rendition:layout"]/text()', namespaces=default_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): @@ -49,13 +71,7 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): 'dc': 'http://purl.org/dc/elements/1.1/' } - epub_zip = zipfile.ZipFile(tmp_file_path) - - txt = epub_zip.read('META-INF/container.xml') - tree = etree.fromstring(txt) - cf_name = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0] - cf = epub_zip.read(cf_name) - tree = etree.fromstring(cf) + tree, cf_name = get_content_opf(tmp_file_path, ns) cover_path = os.path.dirname(cf_name) @@ -73,20 +89,20 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): elif s == 'date': epub_metadata[s] = tmp[0][:10] else: - epub_metadata[s] = tmp[0] + epub_metadata[s] = tmp[0].strip() else: epub_metadata[s] = 'Unknown' 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 @@ -98,15 +114,19 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): epub_metadata = parse_epub_series(ns, tree, epub_metadata) + epub_zip = zipfile.ZipFile(tmp_file_path) cover_file = parse_epub_cover(ns, tree, epub_zip, cover_path, tmp_file_path) identifiers = [] for node in p.xpath('dc:identifier', namespaces=ns): - identifier_name=node.attrib.values()[-1]; - identifier_value=node.text; - if identifier_name in ('uuid','calibre'): - continue; - identifiers.append( [identifier_name, identifier_value] ) + 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 + identifiers.append([identifier_name, identifier_value]) if not epub_metadata['title']: title = original_file_name @@ -131,40 +151,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/epub_helper.py b/cps/epub_helper.py new file mode 100644 index 00000000..d221dff3 --- /dev/null +++ b/cps/epub_helper.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2018 lemmsh, Kennyl, Kyosfonica, matthazinski +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import zipfile +from lxml import etree + +from . import isoLanguages + +default_ns = { + 'n': 'urn:oasis:names:tc:opendocument:xmlns:container', + 'pkg': 'http://www.idpf.org/2007/opf', +} + +OPF_NAMESPACE = "http://www.idpf.org/2007/opf" +PURL_NAMESPACE = "http://purl.org/dc/elements/1.1/" + +OPF = "{%s}" % OPF_NAMESPACE +PURL = "{%s}" % PURL_NAMESPACE + +etree.register_namespace("opf", OPF_NAMESPACE) +etree.register_namespace("dc", PURL_NAMESPACE) + +OPF_NS = {None: OPF_NAMESPACE} # the default namespace (no prefix) +NSMAP = {'dc': PURL_NAMESPACE, 'opf': OPF_NAMESPACE} + + +def updateEpub(src, dest, filename, data, ): + # create a temp copy of the archive without filename + with zipfile.ZipFile(src, 'r') as zin: + with zipfile.ZipFile(dest, 'w') as zout: + zout.comment = zin.comment # preserve the comment + for item in zin.infolist(): + if item.filename != filename: + zout.writestr(item, zin.read(item.filename)) + + # now add filename with its new data + with zipfile.ZipFile(dest, mode='a', compression=zipfile.ZIP_DEFLATED) as zf: + zf.writestr(filename, data) + + +def get_content_opf(file_path, ns=default_ns): + epubZip = zipfile.ZipFile(file_path) + txt = epubZip.read('META-INF/container.xml') + tree = etree.fromstring(txt) + cf_name = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0] + cf = epubZip.read(cf_name) + + return etree.fromstring(cf), cf_name + + +def create_new_metadata_backup(book, custom_columns, export_language, translated_cover_name, lang_type=3): + # generate root package element + package = etree.Element(OPF + "package", nsmap=OPF_NS) + package.set("unique-identifier", "uuid_id") + package.set("version", "2.0") + + # generate metadata element and all sub elements of it + metadata = etree.SubElement(package, "metadata", nsmap=NSMAP) + identifier = etree.SubElement(metadata, PURL + "identifier", id="calibre_id", nsmap=NSMAP) + identifier.set(OPF + "scheme", "calibre") + identifier.text = str(book.id) + identifier2 = etree.SubElement(metadata, PURL + "identifier", id="uuid_id", nsmap=NSMAP) + identifier2.set(OPF + "scheme", "uuid") + identifier2.text = book.uuid + for i in book.identifiers: + identifier = etree.SubElement(metadata, PURL + "identifier", nsmap=NSMAP) + identifier.set(OPF + "scheme", i.format_type()) + identifier.text = str(i.val) + title = etree.SubElement(metadata, PURL + "title", nsmap=NSMAP) + title.text = book.title + for author in book.authors: + creator = etree.SubElement(metadata, PURL + "creator", nsmap=NSMAP) + creator.text = str(author.name) + creator.set(OPF + "file-as", book.author_sort) # ToDo Check + creator.set(OPF + "role", "aut") + contributor = etree.SubElement(metadata, PURL + "contributor", nsmap=NSMAP) + contributor.text = "calibre (5.7.2) [https://calibre-ebook.com]" + contributor.set(OPF + "file-as", "calibre") # ToDo Check + contributor.set(OPF + "role", "bkp") + + date = etree.SubElement(metadata, PURL + "date", nsmap=NSMAP) + date.text = '{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format(d=book.pubdate) + if book.comments and book.comments[0].text: + for b in book.comments: + description = etree.SubElement(metadata, PURL + "description", nsmap=NSMAP) + description.text = b.text + for b in book.publishers: + publisher = etree.SubElement(metadata, PURL + "publisher", nsmap=NSMAP) + publisher.text = str(b.name) + if not book.languages: + language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP) + language.text = export_language + else: + for b in book.languages: + language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP) + language.text = str(b.lang_code) if lang_type == 3 else isoLanguages.get(part3=b.lang_code).part1 + for b in book.tags: + subject = etree.SubElement(metadata, PURL + "subject", nsmap=NSMAP) + subject.text = str(b.name) + etree.SubElement(metadata, "meta", name="calibre:author_link_map", + content="{" + ", ".join(['"' + str(a.name) + '": ""' for a in book.authors]) + "}", + nsmap=NSMAP) + for b in book.series: + etree.SubElement(metadata, "meta", name="calibre:series", + content=str(str(b.name)), + nsmap=NSMAP) + if book.series: + etree.SubElement(metadata, "meta", name="calibre:series_index", + content=str(book.series_index), + nsmap=NSMAP) + if len(book.ratings) and book.ratings[0].rating > 0: + etree.SubElement(metadata, "meta", name="calibre:rating", + content=str(book.ratings[0].rating), + nsmap=NSMAP) + etree.SubElement(metadata, "meta", name="calibre:timestamp", + content='{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format( + d=book.timestamp), + nsmap=NSMAP) + etree.SubElement(metadata, "meta", name="calibre:title_sort", + content=book.sort, + nsmap=NSMAP) + sequence = 0 + for cc in custom_columns: + value = None + extra = None + cc_entry = getattr(book, "custom_column_" + str(cc.id)) + if cc_entry.__len__(): + value = [c.value for c in cc_entry] if cc.is_multiple else cc_entry[0].value + extra = cc_entry[0].extra if hasattr(cc_entry[0], "extra") else None + etree.SubElement(metadata, "meta", name="calibre:user_metadata:#{}".format(cc.label), + content=cc.to_json(value, extra, sequence), + nsmap=NSMAP) + sequence += 1 + + # generate guide element and all sub elements of it + # Title is translated from default export language + guide = etree.SubElement(package, "guide") + etree.SubElement(guide, "reference", type="cover", title=translated_cover_name, href="cover.jpg") + + return package + +def replace_metadata(tree, package): + rep_element = tree.xpath('/pkg:package/pkg:metadata', namespaces=default_ns)[0] + new_element = package.xpath('//metadata', namespaces=default_ns)[0] + tree.replace(rep_element, new_element) + return etree.tostring(tree, + xml_declaration=True, + encoding='utf-8', + pretty_print=True).decode('utf-8') + + 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/file_helper.py b/cps/file_helper.py new file mode 100644 index 00000000..7c3e5291 --- /dev/null +++ b/cps/file_helper.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2023 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from tempfile import gettempdir +import os +import shutil + +def get_temp_dir(): + tmp_dir = os.path.join(gettempdir(), 'calibre_web') + if not os.path.isdir(tmp_dir): + os.mkdir(tmp_dir) + return tmp_dir + + +def del_temp_dir(): + tmp_dir = os.path.join(gettempdir(), 'calibre_web') + shutil.rmtree(tmp_dir) diff --git a/cps/gdrive.py b/cps/gdrive.py index 60e3d47b..4d110f83 100644 --- a/cps/gdrive.py +++ b/cps/gdrive.py @@ -23,7 +23,6 @@ import os import hashlib import json -import tempfile from uuid import uuid4 from time import time from shutil import move, copyfile @@ -34,6 +33,7 @@ from flask_login import login_required from . import logger, gdriveutils, config, ub, calibre_db, csrf from .admin import admin_required +from .file_helper import get_temp_dir gdrive = Blueprint('gdrive', __name__, url_prefix='/gdrive') log = logger.create() @@ -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") @@ -139,9 +139,7 @@ try: dbpath = os.path.join(config.config_calibre_dir, "metadata.db").encode() if not response['deleted'] and response['file']['title'] == 'metadata.db' \ and response['file']['md5Checksum'] != hashlib.md5(dbpath): # nosec - tmp_dir = os.path.join(tempfile.gettempdir(), 'calibre_web') - if not os.path.isdir(tmp_dir): - os.mkdir(tmp_dir) + tmp_dir = get_temp_dir() log.info('Database file updated') copyfile(dbpath, os.path.join(tmp_dir, "metadata.db_" + str(current_milli_time()))) diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index e2e0a536..b1d30596 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -33,7 +33,7 @@ try: except ImportError: from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.exc import OperationalError, InvalidRequestError, IntegrityError -from sqlalchemy.sql.expression import text +from sqlalchemy.orm.exc import StaleDataError try: from httplib2 import __version__ as httplib2_version @@ -146,7 +146,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) @@ -173,30 +173,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): @@ -318,7 +300,7 @@ def getFolderId(path, drive): session.commit() else: currentFolderId = storedPathName.gdrive_id - except (OperationalError, IntegrityError) as ex: + except (OperationalError, IntegrityError, StaleDataError) as ex: log.error_or_exception('Database error: {}'.format(ex)) session.rollback() except ApiRequestError as ex: @@ -343,7 +325,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() @@ -421,7 +403,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('/') @@ -434,7 +416,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" % @@ -555,7 +540,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 @@ -577,6 +562,7 @@ def deleteDatabaseEntry(ID): # Gets cover file from gdrive +# ToDo: Check is this right everyone get read permissions on cover files? def get_cover_via_gdrive(cover_path): df = getFileFromEbooksFolder(cover_path, 'cover.jpg') if df: @@ -599,6 +585,29 @@ def get_cover_via_gdrive(cover_path): else: return None +# Gets cover file from gdrive +def get_metadata_backup_via_gdrive(metadata_path): + df = getFileFromEbooksFolder(metadata_path, 'metadata.opf') + if df: + if not session.query(PermissionAdded).filter(PermissionAdded.gdrive_id == df['id']).first(): + df.GetPermissions() + df.InsertPermission({ + 'type': 'anyone', + 'value': 'anyone', + 'role': 'writer', # ToDo needs write access + 'withLink': True}) + permissionAdded = PermissionAdded() + permissionAdded.gdrive_id = df['id'] + session.add(permissionAdded) + try: + session.commit() + except OperationalError as ex: + log.error_or_exception('Database error: {}'.format(ex)) + session.rollback() + return df.metadata.get('webContentLink') + else: + return None + # Creates chunks for downloading big files def partial(total_byte_len, part_size_limit): s = [] diff --git a/cps/helper.py b/cps/helper.py index a16245fa..5484f2c7 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -18,20 +18,22 @@ # along with this program. If not, see . import os +import random import io -import sys import mimetypes import re import shutil import socket from datetime import datetime, timedelta -from tempfile import gettempdir import requests import unidecode +from uuid import uuid4 +from lxml import etree from flask import send_from_directory, make_response, redirect, abort, url_for 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 from sqlalchemy.sql.expression import true, false, and_, or_, text, func from sqlalchemy.exc import InvalidRequestError, OperationalError @@ -54,10 +56,13 @@ from .tasks.convert import TaskConvert from . import logger, config, db, ub, fs from . import gdriveutils as gd from .constants import STATIC_DIR as _STATIC_DIR, CACHE_TYPE_THUMBNAILS, THUMBNAIL_TYPE_COVER, THUMBNAIL_TYPE_SERIES, SUPPORTED_CALIBRE_BINARIES -from .subproc_wrapper import process_wait +from .subproc_wrapper import process_wait, process_open from .services.worker import WorkerThread from .tasks.mail import TaskEmail from .tasks.thumbnail import TaskClearCoverThumbnailCache, TaskGenerateCoverThumbnails +from .tasks.metadata_backup import TaskBackupMetadata +from .file_helper import get_temp_dir +from .epub_helper import get_content_opf, create_new_metadata_backup, updateEpub, replace_metadata log = logger.create() @@ -72,93 +77,93 @@ except (ImportError, RuntimeError) as e: # Convert existing book entry to new format -def convert_book_format(book_id, calibre_path, old_book_format, new_book_format, user_id, kindle_mail=None): +def convert_book_format(book_id, calibre_path, old_book_format, new_book_format, user_id, ereader_mail=None): book = calibre_db.get_book(book_id) data = calibre_db.get_book_format(book.id, old_book_format) - file_path = os.path.join(calibre_path, book.path, data.name) 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 kindle_mail: + if ereader_mail: settings = config.get_mail_settings() - settings['subject'] = _('Send to Kindle') # 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) settings['old_book_format'] = old_book_format settings['new_book_format'] = new_book_format - WorkerThread.add(user_id, TaskConvert(file_path, book.id, txt, settings, kindle_mail, user_id)) + WorkerThread.add(user_id, TaskConvert(file_path, book.id, txt, settings, ereader_mail, user_id)) return None # Texts are not lazy translated as they are supposed to get send out as is -def send_test_mail(kindle_mail, user_name): - WorkerThread.add(user_name, TaskEmail(_(u'Calibre-Web test e-mail'), None, None, - config.get_mail_settings(), kindle_mail, N_(u"Test e-mail"), - _(u'This e-mail has been sent via Calibre-Web.'))) +def send_test_mail(ereader_mail, user_name): + 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 informations:\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 -def check_send_to_kindle_with_converter(formats): +def check_send_to_ereader_with_converter(formats): book_formats = list() - if 'EPUB' in formats and 'MOBI' not in formats: - book_formats.append({'format': 'Mobi', + 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 Kindle', - orig='Epub', - format='Mobi')}) - if 'AZW3' in formats and 'MOBI' not in formats: - book_formats.append({'format': 'Mobi', + '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 Kindle', + 'text': _('Convert %(orig)s to %(format)s and send to eReader', orig='Azw3', - format='Mobi')}) + format='Epub')}) return book_formats -def check_send_to_kindle(entry): +def check_send_to_ereader(entry): """ - returns all available book formats for sending to Kindle + returns all available book formats for sending to eReader """ formats = list() book_formats = list() @@ -166,30 +171,30 @@ def check_send_to_kindle(entry): for ele in iter(entry.data): if ele.uncompressed_size < config.mail_size: formats.append(ele.format) - if 'MOBI' in formats: - book_formats.append({'format': 'Mobi', + if 'EPUB' in formats: + book_formats.append({'format': 'Epub', 'convert': 0, - 'text': _('Send %(format)s to Kindle', 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 Kindle', 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 Kindle', format='Azw')}) + 'text': _('Send %(format)s to eReader', format='Azw')}) if config.config_converterpath: - book_formats.extend(check_send_to_kindle_with_converter(formats)) + 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): @@ -199,30 +204,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 kindle email, -# 2: If Epub file is existing, it's converted and send to kindle email, -# 3: If Pdf file is existing, it's directly send to kindle email -def send_mail(book_id, book_format, convert, kindle_mail, calibrepath, user_id): +# 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, kindle_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, kindle_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 Kindle", book=link) - WorkerThread.add(user_id, TaskEmail(_(u"Send to Kindle"), book.path, converted_file_name, - config.get_mail_settings(), kindle_mail, - email_text, _(u'This e-mail has been sent via Calibre-Web.'))) + 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, _('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): @@ -230,19 +235,18 @@ 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) - filename_encoding_for_length = 'utf-16' if sys.platform == "win32" or sys.platform == "darwin" else 'utf-8' - value = value.encode(filename_encoding_for_length)[:chars].decode('utf-8', errors='ignore').strip() + value = value.encode('utf-8')[:chars].decode('utf-8', errors='ignore').strip() if not value: raise ValueError("Filename cannot be empty") @@ -319,12 +323,12 @@ def edit_book_read_status(book_id, read_status=None): try: calibre_db.update_title_sort(config) book = calibre_db.get_filtered_book(book_id) - read_status = getattr(book, 'custom_column_' + str(config.config_read_column)) - if len(read_status): + book_read_status = getattr(book, 'custom_column_' + str(config.config_read_column)) + if len(book_read_status): if read_status is None: - read_status[0].value = not read_status[0].value + book_read_status[0].value = not book_read_status[0].value else: - read_status[0].value = read_status is True + book_read_status[0].value = read_status is True calibre_db.session.commit() else: cc_class = db.cc_classes[config.config_read_column] @@ -333,11 +337,11 @@ def edit_book_read_status(book_id, read_status=None): calibre_db.session.commit() except (KeyError, AttributeError, IndexError): log.error( - "Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) - return "Custom Column No.{} is not existing in calibre database".format(config.config_read_column) + "Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) + 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 "" @@ -412,8 +416,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())) @@ -506,25 +510,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('\\', '/') @@ -596,7 +600,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 @@ -608,7 +612,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) @@ -617,11 +621,35 @@ def reset_password(user_id): ub.session.rollback() return 0, None - -def generate_random_password(): +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)]) + + # 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): @@ -636,28 +664,47 @@ 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 def valid_email(email): email = email.strip() - # 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")) + # if email is not deleted + if 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("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 ################################# @@ -680,35 +727,35 @@ def update_dir_structure(book_id, def delete_book(book, calibrepath, book_format): if not book_format: - clear_cover_thumbnail_cache(book.id) ## here it breaks + clear_cover_thumbnail_cache(book.id) ## here it breaks + calibre_db.delete_dirty_metadata(book.id) if config.config_use_google_drive: return delete_book_gdrive(book, book_format) else: 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 @@ -724,26 +771,26 @@ 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: - cover_file_path = os.path.join(config.config_calibre_dir, book.path) + cover_file_path = os.path.join(config.get_book_path(), book.path) 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): @@ -766,7 +813,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): @@ -805,7 +852,7 @@ def save_cover_from_url(url, book_path): img = advocate.get(url, timeout=(10, 200), allow_redirects=False) # ToDo: Error Handling else: log.error("python module advocate is not installed but is needed") - return False, _("Python module 'advocate' is not installed but is needed for cover downloads") + return False, _("Python module 'advocate' is not installed but is needed for cover uploads") img.raise_for_status() return save_cover(img, book_path) except (socket.gaierror, @@ -830,8 +877,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): @@ -846,8 +893,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 @@ -877,10 +924,7 @@ def save_cover(img, book_path): return False, _("Only jpg/jpeg files are supported as coverfile") if config.config_use_google_drive: - tmp_dir = os.path.join(gettempdir(), 'calibre_web') - - if not os.path.isdir(tmp_dir): - os.mkdir(tmp_dir) + tmp_dir = get_temp_dir() ret, message = save_cover_from_filestorage(tmp_dir, "uploaded_cover.jpg", img) if ret is True: gd.uploadFileToEbooksFolder(os.path.join(book_path, 'cover.jpg').replace("\\", "/"), @@ -890,33 +934,92 @@ def save_cover(img, book_path): else: return False, message else: - return save_cover_from_filestorage(os.path.join(config.config_calibre_dir, book_path), "cover.jpg", img) + return save_cover_from_filestorage(os.path.join(config.get_book_path(), book_path), "cover.jpg", img) def do_download_file(book, book_format, client, data, headers): + book_name = data.name if config.config_use_google_drive: # startTime = time.time() - df = gd.getFileFromEbooksFolder(book.path, data.name + "." + book_format) + df = gd.getFileFromEbooksFolder(book.path, book_name + "." + book_format) # log.debug('%s', time.time() - startTime) if df: - return gd.do_gdrive_download(df, headers) + if config.config_embed_metadata and ( + (book_format == "kepub" and config.config_kepubifypath ) or + (book_format != "kepub" and config.config_binariesdir)): + output_path = os.path.join(config.config_calibre_dir, book.path) + if not os.path.exists(output_path): + os.makedirs(output_path) + output = os.path.join(config.config_calibre_dir, book.path, book_name + "." + book_format) + gd.downloadFile(book.path, book_name + "." + book_format, output) + if book_format == "kepub" and config.config_kepubifypath: + filename, download_name = do_kepubify_metadata_replace(book, output) + elif book_format != "kepub" and config.config_binariesdir: + filename, download_name = do_calibre_export(book.id, book_format) + else: + return gd.do_gdrive_download(df, headers) else: abort(404) else: - filename = os.path.join(config.config_calibre_dir, book.path) - if not os.path.isfile(os.path.join(filename, data.name + "." + book_format)): + filename = os.path.join(config.get_book_path(), book.path) + if not os.path.isfile(os.path.join(filename, book_name + "." + book_format)): # ToDo: improve error handling - log.error('File not found: %s', os.path.join(filename, data.name + "." + book_format)) + log.error('File not found: %s', os.path.join(filename, book_name + "." + book_format)) if client == "kobo" and book_format == "kepub": headers["Content-Disposition"] = headers["Content-Disposition"].replace(".kepub", ".kepub.epub") - response = make_response(send_from_directory(filename, data.name + "." + book_format)) - # ToDo Check headers parameter - for element in headers: - response.headers[element[0]] = element[1] - log.info('Downloading file: {}'.format(os.path.join(filename, data.name + "." + book_format))) - return response + if book_format == "kepub" and config.config_kepubifypath and config.config_embed_metadata: + filename, download_name = do_kepubify_metadata_replace(book, os.path.join(filename, + book_name + "." + book_format)) + elif book_format != "kepub" and config.config_binariesdir and config.config_embed_metadata: + filename, download_name = do_calibre_export(book.id, book_format) + else: + download_name = book_name + + response = make_response(send_from_directory(filename, download_name + "." + book_format)) + # ToDo Check headers parameter + for element in headers: + response.headers[element[0]] = element[1] + log.info('Downloading file: {}'.format(os.path.join(filename, book_name + "." + book_format))) + return response + + +def do_kepubify_metadata_replace(book, file_path): + custom_columns = (calibre_db.session.query(db.CustomColumns) + .filter(db.CustomColumns.mark_for_delete == 0) + .filter(db.CustomColumns.datatype.notin_(db.cc_exceptions)) + .order_by(db.CustomColumns.label).all()) + + tree, cf_name = get_content_opf(file_path) + package = create_new_metadata_backup(book, custom_columns, current_user.locale, _("Cover"), lang_type=2) + content = replace_metadata(tree, package) + tmp_dir = get_temp_dir() + temp_file_name = str(uuid4()) + # open zipfile and replace metadata block in content.opf + updateEpub(file_path, os.path.join(tmp_dir, temp_file_name + ".kepub"), cf_name, content) + return tmp_dir, temp_file_name + + +def do_calibre_export(book_id, book_format, ): + try: + quotes = [3, 5, 7, 9] + tmp_dir = get_temp_dir() + calibredb_binarypath = get_calibre_binarypath("calibredb") + temp_file_name = str(uuid4()) + opf_command = [calibredb_binarypath, 'export', '--dont-write-opf', '--with-library', config.config_calibre_dir, + '--to-dir', tmp_dir, '--formats', book_format, "--template", "{}".format(temp_file_name), + str(book_id)] + p = process_open(opf_command, quotes) + _, err = p.communicate() + if err: + log.error('Metadata embedder encountered an error: %s', err) + return tmp_dir, temp_file_name + except OSError as ex: + # ToDo real error handling + log.error_or_exception(ex) + return None, None + ################################## @@ -937,7 +1040,48 @@ def check_unrar(unrar_location): except (OSError, UnicodeDecodeError) as err: log.error_or_exception(err) - return _('Error excecuting UnRar') + return _('Error executing UnRar') + + +def check_calibre(calibre_location): + if not calibre_location: + return + + if not os.path.exists(calibre_location): + return _('Could not find the specified directory') + + if not os.path.isdir(calibre_location): + return _('Please specify a directory, not a file') + + try: + supported_binary_paths = [os.path.join(calibre_location, binary) + for binary in SUPPORTED_CALIBRE_BINARIES.values()] + binaries_available = [os.path.isfile(binary_path) for binary_path in supported_binary_paths] + binaries_executable = [os.access(binary_path, os.X_OK) for binary_path in supported_binary_paths] + if all(binaries_available) and all(binaries_executable): + values = [process_wait([binary_path, "--version"], pattern='\(calibre (.*)\)') + for binary_path in supported_binary_paths] + if all(values): + version = values[0].group(1) + log.debug("calibre version %s", version) + else: + return _('Calibre binaries not viable') + else: + ret_val = [] + missing_binaries=[path for path, available in + zip(SUPPORTED_CALIBRE_BINARIES.values(), binaries_available) if not available] + + missing_perms=[path for path, available in + zip(SUPPORTED_CALIBRE_BINARIES.values(), binaries_executable) if not available] + if missing_binaries: + ret_val.append(_('Missing calibre binaries: %(missing)s', missing=", ".join(missing_binaries))) + if missing_perms: + ret_val.append(_('Missing executable permissions: %(missing)s', missing=", ".join(missing_perms))) + return ", ".join(ret_val) + + except (OSError, UnicodeDecodeError) as err: + log.error_or_exception(err) + return _('Error excecuting Calibre') def check_calibre(calibre_location): @@ -993,43 +1137,49 @@ def tags_filters(): # checks if domain is in database (including wildcards) -# example SELECT * FROM @TABLE WHERE 'abcdefg' LIKE Name; +# example SELECT * FROM @TABLE WHERE 'abcdefg' LIKE Name; # from https://code.luasoftware.com/tutorials/flask/execute-raw-sql-in-flask-sqlalchemy/ # in all calls the email address is checked for validity def check_valid_domain(domain_text): sql = "SELECT * FROM registration WHERE (:domain LIKE domain and allow = 1);" - result = ub.session.query(ub.Registration).from_statement(text(sql)).params(domain=domain_text).all() - if not len(result): + if not len(ub.session.query(ub.Registration).from_statement(text(sql)).params(domain=domain_text).all()): return False sql = "SELECT * FROM registration WHERE (:domain LIKE domain and allow = 0);" - result = ub.session.query(ub.Registration).from_statement(text(sql)).params(domain=domain_text).all() - return not len(result) + return not len(ub.session.query(ub.Registration).from_statement(text(sql)).params(domain=domain_text).all()) def get_download_link(book_id, book_format, client): book_format = book_format.split(".")[0] book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) - data1= "" if book: data1 = calibre_db.get_book_format(book.id, book_format.upper()) + if data1: + # collect downloaded books only for registered user and not for anonymous user + if current_user.is_authenticated: + ub.update_download(book_id, int(current_user.id)) + file_name = book.title + if len(book.authors) > 0: + file_name = file_name + ' - ' + book.authors[0].name + file_name = get_valid_filename(file_name, replace_whitespace=False) + 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), book_format, quote(file_name), book_format) + return do_download_file(book, book_format, client, data1, headers) else: log.error("Book id {} not found for downloading".format(book_id)) - abort(404) - if data1: - # collect downloaded books only for registered user and not for anonymous user - if current_user.is_authenticated: - ub.update_download(book_id, int(current_user.id)) - file_name = book.title - if len(book.authors) > 0: - file_name = file_name + ' - ' + book.authors[0].name - file_name = get_valid_filename(file_name, replace_whitespace=False) - 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) - return do_download_file(book, book_format, client, data1, headers) - else: - abort(404) + abort(404) + + +def get_calibre_binarypath(binary): + binariesdir = config.config_binariesdir + if binariesdir: + try: + return os.path.join(binariesdir, SUPPORTED_CALIBRE_BINARIES[binary]) + except KeyError as ex: + log.error("Binary not supported by Calibre-Web: %s", SUPPORTED_CALIBRE_BINARIES[binary]) + pass + return "" def get_calibre_binarypath(binary): @@ -1066,3 +1216,11 @@ def add_book_to_thumbnail_cache(book_id): def update_thumbnail_cache(): if config.schedule_generate_book_covers: WorkerThread.add(None, TaskGenerateCoverThumbnails()) + + +def set_all_metadata_dirty(): + WorkerThread.add(None, TaskBackupMetadata(export_language=get_locale(), + translated_title=_("Cover"), + set_dirty=True, + task_message=N_("Queue all books for metadata backup")), + hidden=False) diff --git a/cps/iso_language_names.py b/cps/iso_language_names.py index f86e5612..4b9a8ef9 100644 --- a/cps/iso_language_names.py +++ b/cps/iso_language_names.py @@ -2517,1282 +2517,1188 @@ LANGUAGE_NAMES = { "zxx": "pas de contenu linguistique", "zza": "zaza" }, - "hu": { - "aar": "Afar", - "abk": "Abház", - "ace": "Akinéz", - "ach": "Acoli", + "gl": { + "abk": "Abjaziano", + "ace": "Achinés", + "ach": "Acolí", "ada": "Adangme", - "ady": "Adyghe", + "ady": "Adigué", + "aar": "Afar", "afh": "Afrihili", - "afr": "Afrikaans", - "ain": "ainu (Japán)", - "aka": "akan", - "akk": "akkád", - "ale": "aleut", - "alt": "altáji; déli", - "amh": "amhara", - "ang": "angol; óangol (kb. 450-1100)", - "anp": "angika", - "ara": "arab", - "arc": "arámi; hivatalos (i.e. 700- i.e. 300)", - "arg": "aragóniai", - "arn": "Mapudungun", - "arp": "arapaho", - "arw": "arawak", - "asm": "asszámi", - "ast": "Asturian", - "ava": "avar", - "ave": "avesztai", - "awa": "avádi", - "aym": "ajmara", - "aze": "azeri", - "bak": "baskír", - "bal": "baluchi", - "bam": "bambara", - "ban": "balinéz", - "bas": "Basa (Cameroon)", - "bej": "beja", - "bel": "belarusz", + "afr": "Africáner", + "ain": "Ainu (Xapón)", + "aka": "Akan", + "akk": "Acadio", + "sqi": "Albanian", + "ale": "Aleutiano", + "amh": "Amhárico", + "anp": "Angika", + "ara": "Árabe", + "arg": "Aragonés", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "Armenian", + "asm": "Asamés", + "ast": "Asturiano", + "ava": "Avárico", + "ave": "Avéstico", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Acerbaixano", + "ban": "Balinés", + "bal": "Baluchi", + "bam": "Bambara", + "bas": "Basa (Camerún)", + "bak": "Bashkir", + "eus": "Vasco", + "bej": "Beja", + "bel": "Bielorruso", "bem": "Bemba (Zambia)", - "ben": "bengáli", - "bho": "bhodzspuri", - "bik": "bikol", - "bin": "bini", - "bis": "biszlama", + "ben": "Bengalí", "bit": "Berinomo", - "bla": "szikszika", - "bod": "tibeti", - "bos": "bosnyák", - "bra": "bradzs", - "bre": "breton", - "bua": "burját", - "bug": "buginéz", - "bul": "bolgár", + "bho": "Bhojpuri", + "bik": "Bikol", "byn": "Bilin", - "cad": "caddo", - "car": "Carib; Galibi", - "cat": "katalán", - "ceb": "cebuano", - "ces": "cseh", - "cha": "csamorro", - "chb": "csibcsa", - "che": "csecsen", - "chg": "chagati", - "chk": "csukéz", - "chm": "Mari (Russia)", - "chn": "chinook zsargon", - "cho": "csoktó", - "chp": "csippeva", - "chr": "cserokí", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Símbolos Blis", + "bos": "Bosnio", + "bra": "Braj", + "bre": "Bretón", + "bug": "Buginés", + "bul": "Búlgaro", + "bua": "Buriat", + "mya": "Birmano", + "cad": "Caddo", + "cat": "Catalán", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "Chamorro", + "che": "Checheno", + "chr": "Cherokee", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "Chinés", + "chn": "Chinook; argot", + "chp": "Chipewyan", + "cho": "Choctaw", "cht": "Cholón", - "chu": "szláv; ószláv", - "chv": "csuvas", - "chy": "csejen", - "cop": "kopt", - "cor": "cornwalli", - "cos": "korzikai", - "cre": "cree", - "crh": "Turkish; Crimean", - "csb": "kasubi", - "cym": "velszi", - "dak": "dakota", - "dan": "dán", - "dar": "dargwa", - "del": "delavár", - "den": "Szolga (atapaszkán)", - "deu": "német", - "dgr": "dogrib", - "din": "dinka", + "chk": "Chuukese", + "chv": "Chuvash", + "cop": "Copto", + "cor": "Cornish", + "cos": "Corso", + "cre": "Cree", + "mus": "Creek", + "hrv": "Croata", + "ces": "Checo", + "dak": "Dakota", + "dan": "Danés", + "dar": "Dargwa", + "del": "Delaware", "div": "Dhivehi", - "doi": "Dogri (macrolanguage)", - "dsb": "Sorbian; Lower", - "dse": "Dutch Sign Language", - "dua": "duala", - "dum": "Dutch; Middle (ca. 1050-1350)", - "dyu": "djula", - "dzo": "dzongka", - "efi": "efik", - "egy": "óegyiptomi", - "eka": "ekajuk", - "ell": "modern görög (1453-)", - "elx": "elamita", - "eng": "angol", - "enm": "angol; középkori (1100-1500)", + "din": "Dinka", + "doi": "Dogri (macrolingua)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Holandés", + "dse": "Lingua de signos holandés", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Exipcio (antigo)", + "eka": "Ekajuk", + "elx": "Elamita", + "eng": "Inglés", "enu": "Enu", - "epo": "eszperantó", - "est": "észt", - "eus": "Baszk", - "ewe": "ewe", - "ewo": "ewondo", - "fan": "Fang (Equatorial Guinea)", - "fao": "Feröeri", - "fas": "perzsa", - "fat": "fanti", - "fij": "fidzsi", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estonio", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang (Guinea ecuatorial)", + "fat": "Fanti", + "fao": "Feroés", + "fij": "Fixino", "fil": "Filipino", - "fin": "finn", - "fon": "fon", - "fra": "francia", - "frm": "French; Middle (ca. 1400-1600)", - "fro": "francia; ófrancia (842- kb. 1400)", - "frr": "Frisian; Northern", - "frs": "Frisian; Eastern", - "fry": "Frisian; Western", - "ful": "fula", - "fur": "friul", - "gaa": "ga", - "gay": "gajo", - "gba": "Gbaya (Central African Republic)", - "gez": "gíz", - "gil": "gilberti", - "gla": "Gaelic; Scottish", - "gle": "ír", - "glg": "galíciai", - "glv": "manx", - "gmh": "German; Middle High (ca. 1050-1500)", - "goh": "német; ónémet (kb. 750-1050)", - "gon": "gondi", - "gor": "gorontalo", - "got": "gót", - "grb": "grebo", - "grc": "ógörög (1453-ig)", - "grn": "guarani", - "gsw": "German; Swiss", - "guj": "gudzsarati", - "gwi": "Gwichʼin", - "hai": "haida", - "hat": "Creole; Haitian", - "hau": "hausza", - "haw": "hawaii", - "heb": "héber", - "her": "herero", - "hil": "hiligajnon", - "hin": "hindi", - "hit": "hettita", + "fin": "Finés", + "fon": "Fon", + "fra": "Francés", + "fur": "Friuliano", + "ful": "Fulah", + "gaa": "Ga", + "glg": "Galego", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (República centroafricana)", "hmj": "Ge", - "hmn": "hmong", - "hmo": "hiri motu", - "hrv": "horvát", - "hsb": "Sorbian; Upper", - "hun": "Magyar", - "hup": "hupa", - "hye": "örmény", - "iba": "iba", - "ibo": "igbo", - "ido": "ido", - "iii": "Yi; Sichuan", - "iku": "inuktitut", - "ile": "interlingva", - "ilo": "iloko", - "ina": "interlingva (Nemzetközi Segédnyelv Egyesület)", - "ind": "indonéz", - "inh": "ingus", - "ipk": "inupiak", - "isl": "izlandi", - "ita": "olasz", - "jav": "jávai", - "jbo": "lodzsban", - "jpn": "japán", - "jpr": "judeo-perzsa", - "jrb": "judeo-arab", - "kaa": "kara-kalpak", - "kab": "kabile", - "kac": "kachin", + "gez": "Geez", + "kat": "Xeorxiano", + "deu": "Alemán", + "gil": "Gilbertés", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gótico", + "grb": "Grebo", + "grn": "Guaraní", + "guj": "Gujarati", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Haussa", + "haw": "Hawaiano", + "heb": "Hebreo", + "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": "Iloko", + "ind": "Indonesio", + "inh": "Ingush", + "ina": "Interlingua (lingua internacional auxiliar)", + "ile": "Interlingue", + "iku": "Inuktitut", + "ipk": "Inupiak", + "gle": "Irlandés", + "ita": "Italiano", + "jpn": "Xaponés", + "jav": "Xavanés", + "jrb": "Xudeu-Árabe", + "jpr": "Xudeu-Persa", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", "kal": "Kalaallisut", + "xal": "Kalmyk", "kam": "Kamba (Kenya)", - "kan": "kannada", - "kas": "kasmíri", - "kat": "grúz", - "kau": "kanuri", - "kaw": "kawi", - "kaz": "kazah", - "kbd": "kabardi", - "kha": "kazi", - "khm": "Khmer; Central", - "kho": "kotáni", - "kik": "kikuyu", - "kin": "kinyarwanda", - "kir": "kirgiz", - "kmb": "kimbundu", - "kok": "Konkani (macrolanguage)", - "kom": "komi", - "kon": "kongo", - "kor": "koreai", - "kos": "koszrai", - "kpe": "kpelle", - "krc": "karacsai-balkar", - "krl": "kareliai", - "kru": "kuruk", - "kua": "kuanyama", - "kum": "kumyk", - "kur": "kurd", - "kut": "kutenai", - "lad": "ladino", - "lah": "landa", - "lam": "lamba", - "lao": "lao", - "lat": "latin", - "lav": "lett", - "lez": "lezgi", - "lim": "Limburgan", - "lin": "lingala", - "lit": "litván", - "lol": "mongo", - "loz": "lozi", - "ltz": "Luxembourgish", - "lua": "luba-lulua", - "lub": "luba-katanga", - "lug": "ganda", - "lui": "luisendo", - "lun": "lunda", - "luo": "luo (Kenya és Tanzánia)", - "lus": "lushai", - "mad": "maduri", - "mag": "magahi", - "mah": "Marshallese", - "mai": "maithili", - "mak": "makasar", - "mal": "malajalam", - "man": "mandingo", - "mar": "marathi", - "mas": "maszáj", - "mdf": "moksa", - "mdr": "mandar", + "kan": "Kannada", + "kau": "Kanuri", + "kaa": "Kara-Kalpak", + "krc": "Karachay-Balkar", + "krl": "Karelian", + "kas": "Kashmiri", + "csb": "Kashubiano", + "kaw": "Kawi", + "kaz": "Kazako", + "kha": "Khasi", + "kho": "Khotanese", + "kik": "Kikuyu", + "kmb": "Kimbundu", + "kin": "Kinyarwanda", + "kir": "Kirghizo", + "tlh": "Klingon", + "kom": "Komi", + "kon": "Kongo", + "kok": "Konkani (macrolingua)", + "kor": "Coreano", + "kos": "Kosraeano", + "kpe": "Kpelle", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Kurdo", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "Laosiano", + "lat": "Latín", + "lav": "Letón", + "lez": "Lezghiano", + "lim": "Limburgués", + "lin": "Lingala", + "lit": "Lituano", + "jbo": "Lojban", + "loz": "Lozi", + "lub": "Luba-Katanga", + "lua": "Luba-Lulua", + "lui": "Luiseno", + "smj": "Sami Lule", + "lun": "Lunda", + "luo": "Luo (Kenia e Tanzania)", + "lus": "Lushai", + "ltz": "Luxemburgués", + "mkd": "Macedonio", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "Malgache", + "msa": "Malayo (macroLingua)", + "mal": "Malayalamo", + "mlt": "Maltés", + "mnc": "Manchu", + "mdr": "Mandar", + "man": "Mandingo", + "mni": "Manipuri", + "glv": "Manx [Gaélico de Manx]", + "mri": "Maorí", + "arn": "Mapudungun", + "mar": "Marath", + "chm": "Mari (Rusia)", + "mah": "Marshalés", + "mwr": "Marwari", + "mas": "Masai", "men": "Mende (Sierra Leone)", - "mga": "közép-ír (900-1200)", "mic": "Mi'kmaq", - "min": "minangkabau", - "mis": "Uncoded languages", - "mkd": "macedón", - "mlg": "malagasy", - "mlt": "máltai", - "mnc": "manchu", - "mni": "manipuri", - "moh": "mohawk", - "mon": "mongol", - "mos": "mossi", - "mri": "maori", - "msa": "Malay (macrolanguage)", - "mul": "több nyelv", - "mus": "creek", - "mwl": "mirandese", - "mwr": "marwari", - "mya": "burmai", - "myv": "erzija", - "nap": "nápolyi", - "nau": "nauru", - "nav": "Navajo", - "nbl": "ndebele (déli)", - "nde": "ndebele (északi)", - "ndo": "ndonga", - "nds": "German; Low", - "nep": "nepáli", - "new": "Bhasa; Nepal", - "nia": "nias", - "niu": "niuei", - "nld": "holland", - "nno": "norvég (nynorsk)", - "nob": "Norwegian Bokmål", - "nog": "nogai", - "non": "norvég; ónorvég", - "nor": "norvég", + "min": "Minangkabau", + "mwl": "Mirandés", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Varios idiomas", "nqo": "N'Ko", - "nso": "sotho (északi)", - "nwc": "newari; ónewari", + "nau": "Naurí", + "nav": "Navajo", + "ndo": "Ndonga", + "nap": "Neapolitano", + "nia": "Nias", + "niu": "Niués", + "zxx": "Sen contido lingüístico", + "nog": "Nogai", + "nor": "Noruegués", + "nob": "Noruego Bokmål", + "nno": "Noruegués nynorsk", + "nym": "Nyamwezi", "nya": "Nyanja", - "nym": "nyamwezi", - "nyn": "nyankole", - "nyo": "nyoro", - "nzi": "nzima", - "oci": "Occitan (post 1500)", - "oji": "odzsibwa", - "ori": "orija", - "orm": "oromo", - "osa": "oszage", - "oss": "Ossetian", - "ota": "török (ottomán) (1500-1928)", - "pag": "pangasini", - "pal": "pahlavi", - "pam": "pampanga", - "pan": "Panjabi", - "pap": "papiamento", - "pau": "palaui", - "peo": "Persian; Old (ca. 600-400 B.C.)", - "phn": "főníciai", - "pli": "pali", - "pol": "lengyel", - "pon": "ponpei", - "por": "portugál", - "pro": "provanszál; ó (1500-ig)", - "pus": "pushto", - "que": "kecsua", - "raj": "radzsasztani", - "rap": "rapanui", - "rar": "Maori; Cook Islands", - "roh": "Romansh", - "rom": "roma", - "ron": "román", - "run": "rundi", - "rup": "Romanian; Macedo-", - "rus": "orosz", - "sad": "sandawe", - "sag": "szango", - "sah": "jakut", - "sam": "arámi; szamaritánus", - "san": "szankszrit", - "sas": "szaszak", - "sat": "szantáli", - "scn": "friuli", - "sco": "skót", - "sel": "szelkup", - "sga": "ír; óír (900-ig)", - "shn": "shan", - "sid": "szidamo", - "sin": "Sinhala", - "slk": "szlovák", - "slv": "szlovén", - "sma": "Sami; Southern", - "sme": "Sami; Northern", - "smj": "lule szami", - "smn": "Sami; Inari", - "smo": "szamoai", - "sms": "Sami; Skolt", - "sna": "shona", - "snd": "szindi", - "snk": "soninke", - "sog": "sogdi", - "som": "szomáli", - "sot": "sotho; déli", - "spa": "spanyol", - "sqi": "albán", - "srd": "szardíniai", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitano (después de 1500)", + "oji": "Ojibwa", + "orm": "Oromo (Afan)", + "osa": "Osage", + "oss": "Osetio", + "pal": "Pahlavi", + "pau": "Palauan", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinan", + "pan": "Punjabí", + "pap": "Papiamento", + "fas": "Persa", + "phn": "Fenicio", + "pon": "Pohnpeian", + "pol": "Polaco", + "por": "Portugués", + "pus": "Pashtún", + "que": "Quechúa", + "raj": "Rajasthani", + "rap": "Rapanui", + "ron": "Romanés", + "roh": "Romanche", + "rom": "Romaní", + "run": "Kiroundi", + "rus": "Ruso", + "smo": "Samoano", + "sad": "Sandawe", + "sag": "Sango", + "san": "Sánscrito", + "sat": "Santali", + "srd": "Sardo", + "sas": "Sasak", + "sco": "Escocés", + "sel": "Selkup", + "srp": "Serbio", + "srr": "Serer", + "shn": "Shan", + "sna": "Shona", + "scn": "Siciliano", + "sid": "Sidamo", + "bla": "Siksika", + "snd": "Sindhi", + "sin": "Cingalés", + "den": "Eslavo (Athapascan)", + "slk": "Eslovaco", + "slv": "Esloveno", + "sog": "Sogdian", + "som": "Somalí", + "snk": "Soninke", + "spa": "Español", "srn": "Sranan Tongo", - "srp": "szerb", - "srr": "serer", - "ssw": "swati", - "suk": "sukuma", - "sun": "szundanéz", - "sus": "susu", - "sux": "sumér", - "swa": "Swahili (macrolanguage)", - "swe": "svéd", - "syc": "Syriac; Classical", - "syr": "szír", - "tah": "tahiti", - "tam": "tamil", - "tat": "tatár", - "tel": "telugu", - "tem": "timne", - "ter": "tereno", - "tet": "tetum", - "tgk": "tadzsik", - "tgl": "tagalog", - "tha": "thai", - "tig": "tigre", - "tir": "tigrinya", - "tiv": "tiv", - "tkl": "tokelau", - "tlh": "Klingon", - "tli": "tlingit", - "tmh": "tamasek", - "tog": "tonga (nyasza)", - "ton": "tonga (Tonga-szigetek)", - "tpi": "tok pisin", - "tsi": "cimsi", - "tsn": "tswana", - "tso": "tsonga", - "tuk": "türkmén", - "tum": "tumbuka", - "tur": "török", - "tvl": "tuvalu", - "twi": "twi", - "tyv": "tuvini", - "udm": "udmurt", - "uga": "uragi", - "uig": "ujgur", - "ukr": "ukrán", - "umb": "umbundu", - "und": "ismeretlen", - "urd": "urdu", - "uzb": "üzbég", - "vai": "vai", - "ven": "venda", - "vie": "vietnami", - "vol": "volapük", - "vot": "vót", + "suk": "Sukuma", + "sux": "Sumerio", + "sun": "Sundanés", + "sus": "Susu", + "swa": "Swahili (macrolingua)", + "ssw": "Siswati", + "swe": "Sueco", + "syr": "Syriac", + "tgl": "Tagalo", + "tah": "Tahitiano", + "tgk": "Tajiko", + "tmh": "Tamashek", + "tam": "Tamil", + "tat": "Tártaro", + "tel": "Telougou", + "ter": "Tereno", + "tet": "Tetum", + "tha": "Thai", + "bod": "Tibetano", + "tig": "Tigre", + "tir": "Tigrinya", + "tem": "Timne", + "tiv": "Tiv", + "tli": "Tlingit", + "tpi": "Tok Pisin", + "tkl": "Tokelau", + "tog": "Tonga (Nyasa)", + "ton": "Tonga (Islas Tonga)", + "tsi": "Tsimshian", + "tso": "Tsonga", + "tsn": "Setchwana", + "tum": "Tumbuka", + "tur": "Turco", + "tuk": "Turkmeno", + "tvl": "Tuvalu", + "tyv": "Tuvinian", + "twi": "Tchi", + "udm": "Udmurt", + "uga": "Ugarítico", + "uig": "Uiguro", + "ukr": "Ucraíno", + "umb": "Umbundu", + "mis": "Idiomas no codificados", + "und": "Sen determinar", + "urd": "Urdu", + "uzb": "Uzbeko", + "vai": "Vai", + "ven": "Venda", + "vie": "Vietnamita", + "vol": "Volapük", + "vot": "Votic", + "wln": "Valón", + "war": "Waray (Filipinas)", + "was": "Washo", + "cym": "Galés", "wal": "Wolaytta", - "war": "Waray (Philippines)", - "was": "washo", - "wln": "vallon", - "wol": "wolof", - "xal": "Kalmyk", - "xho": "xhosa", - "yao": "yao", - "yap": "jap", - "yid": "jiddis", - "yor": "joruba", - "zap": "Zapoték", - "zbl": "Blissymbols", - "zen": "zenaga", - "zha": "zsuang", - "zho": "kínai", - "zul": "Zulu", - "zun": "zuni", - "zxx": "No linguistic content", - "zza": "Zaza" + "wol": "Wolof", + "xho": "Xhosa", + "sah": "Yakut", + "yao": "Yao", + "yap": "Yapese", + "yid": "Yiddish", + "yor": "Yoruba", + "zap": "Zapoteco", + "zza": "Zaza", + "zen": "Zenaga", + "zha": "Zhuang", + "zul": "Zulú", + "zun": "Zuni" }, - "it": { + "hu": { "aar": "Afar", - "abk": "Abkhazian", - "ace": "Achinese", + "abk": "Abház", + "ace": "Akinéz", "ach": "Acoli", "ada": "Adangme", "ady": "Adyghe", "afh": "Afrihili", "afr": "Afrikaans", - "ain": "Ainu (Giappone)", - "aka": "Akan", - "akk": "Accadico", - "ale": "Aleut", - "alt": "Altai meridionale", - "amh": "Amarico", - "ang": "Inglese antico (ca. 450-1100)", - "anp": "Angika", - "ara": "Arabo", - "arc": "Aramaico ufficiale (700-300 p.e.v.)", - "arg": "Aragonese", + "ain": "ainu (Japán)", + "aka": "akan", + "akk": "akkád", + "ale": "aleut", + "alt": "altáji; déli", + "amh": "amhara", + "ang": "angol; óangol (kb. 450-1100)", + "anp": "angika", + "ara": "arab", + "arc": "arámi; hivatalos (i.e. 700- i.e. 300)", + "arg": "aragóniai", "arn": "Mapudungun", - "arp": "Arapaho", - "arw": "Arawak", - "asm": "Assamese", - "ast": "Asturiano", - "ava": "Avarico", - "ave": "Avestano", - "awa": "Awadhi", - "aym": "Aymara", - "aze": "Azerbaijano", - "bak": "Bashkir", - "bal": "Baluchi", - "bam": "Bambara", - "ban": "Balinese", - "bas": "Basa (Cameru)", - "bej": "Beja", - "bel": "Bielorusso", + "arp": "arapaho", + "arw": "arawak", + "asm": "asszámi", + "ast": "Asturian", + "ava": "avar", + "ave": "avesztai", + "awa": "avádi", + "aym": "ajmara", + "aze": "azeri", + "bak": "baskír", + "bal": "baluchi", + "bam": "bambara", + "ban": "balinéz", + "bas": "Basa (Cameroon)", + "bej": "beja", + "bel": "belarusz", "bem": "Bemba (Zambia)", - "ben": "Bengalese", - "bho": "Bhojpuri", - "bik": "bicol", - "bin": "Bini", - "bis": "bislama", + "ben": "bengáli", + "bho": "bhodzspuri", + "bik": "bikol", + "bin": "bini", + "bis": "biszlama", "bit": "Berinomo", - "bla": "Siksika", - "bod": "Tibetano", - "bos": "Bosniaco", - "bra": "braj", - "bre": "Bretone", - "bua": "Buriat", - "bug": "Buginese", - "bul": "Bulgaro", + "bla": "szikszika", + "bod": "tibeti", + "bos": "bosnyák", + "bra": "bradzs", + "bre": "breton", + "bua": "burját", + "bug": "buginéz", + "bul": "bolgár", "byn": "Bilin", "cad": "caddo", - "car": "Carib (Galibi)", - "cat": "Catalano", - "ceb": "Cebuano", - "ces": "Ceco", - "cha": "Chamorro", - "chb": "Chibcha", - "che": "Chechen", - "chg": "Ciagataico", - "chk": "Chuukese", + "car": "Carib; Galibi", + "cat": "katalán", + "ceb": "cebuano", + "ces": "cseh", + "cha": "csamorro", + "chb": "csibcsa", + "che": "csecsen", + "chg": "chagati", + "chk": "csukéz", "chm": "Mari (Russia)", - "chn": "Chinook jargon", - "cho": "Choctaw", - "chp": "Chipewyan", - "chr": "Cherokee", + "chn": "chinook zsargon", + "cho": "csoktó", + "chp": "csippeva", + "chr": "cserokí", "cht": "Cholón", - "chu": "Slavo antico", - "chv": "Chuvash", - "chy": "Cheyenne", - "cop": "Copto", - "cor": "Cornish", - "cos": "Corso", - "cre": "Cree", - "crh": "Turco; Crimeo", - "csb": "kashubian", - "cym": "Gallese", - "dak": "Dakota", - "dan": "Danese", - "dar": "Dargwa", - "del": "delaware", - "den": "Slave (Athapascan)", - "deu": "Tedesco", - "dgr": "Dogrib", - "din": "Dinca", + "chu": "szláv; ószláv", + "chv": "csuvas", + "chy": "csejen", + "cop": "kopt", + "cor": "cornwalli", + "cos": "korzikai", + "cre": "cree", + "crh": "Turkish; Crimean", + "csb": "kasubi", + "cym": "velszi", + "dak": "dakota", + "dan": "dán", + "dar": "dargwa", + "del": "delavár", + "den": "Szolga (atapaszkán)", + "deu": "német", + "dgr": "dogrib", + "din": "dinka", "div": "Dhivehi", - "doi": "Dogri (macrolingua)", - "dsb": "Lusaziano inferiore", - "dse": "Olandense (linguaggio dei segni)", - "dua": "Duala", - "dum": "Olandese medio (ca. 1050-1350)", - "dyu": "Diula", - "dzo": "Dzongkha", - "efi": "Efik", - "egy": "Egiziano antico", - "eka": "Ekajuk", - "ell": "Greco moderno (1453-)", - "elx": "Elamitico", - "eng": "Inglese", - "enm": "Inglese medio (1100-1500)", + "doi": "Dogri (macrolanguage)", + "dsb": "Sorbian; Lower", + "dse": "Dutch Sign Language", + "dua": "duala", + "dum": "Dutch; Middle (ca. 1050-1350)", + "dyu": "djula", + "dzo": "dzongka", + "efi": "efik", + "egy": "óegyiptomi", + "eka": "ekajuk", + "ell": "modern görög (1453-)", + "elx": "elamita", + "eng": "angol", + "enm": "angol; középkori (1100-1500)", "enu": "Enu", - "epo": "Esperanto", - "est": "Estone", - "eus": "Basco", - "ewe": "Ewe", - "ewo": "Ewondo", - "fan": "Fang (Guinea equatoriale)", - "fao": "Faroese", - "fas": "Persiano", - "fat": "Fanti", - "fij": "Figiano", - "fil": "Filippino", - "fin": "Finlandese", - "fon": "Fon", - "fra": "Francese", - "frm": "Francese medio (ca. 1400-1600)", - "fro": "Francese antico (842-ca. 1400)", - "frr": "Frisone settentrionale", - "frs": "Frisone orientale", - "fry": "Frisone occidentale", - "ful": "Fulah", - "fur": "Friulano", + "epo": "eszperantó", + "est": "észt", + "eus": "Baszk", + "ewe": "ewe", + "ewo": "ewondo", + "fan": "Fang (Equatorial Guinea)", + "fao": "Feröeri", + "fas": "perzsa", + "fat": "fanti", + "fij": "fidzsi", + "fil": "Filipino", + "fin": "finn", + "fon": "fon", + "fra": "francia", + "frm": "French; Middle (ca. 1400-1600)", + "fro": "francia; ófrancia (842- kb. 1400)", + "frr": "Frisian; Northern", + "frs": "Frisian; Eastern", + "fry": "Frisian; Western", + "ful": "fula", + "fur": "friul", "gaa": "ga", - "gay": "gayo", - "gba": "Gbaya (Repubblica centro africana)", - "gez": "Geez", - "gil": "Gilbertese", - "gla": "Gaelico (Scozzese)", - "gle": "Gaelico", - "glg": "Galiziano", - "glv": "Manx", - "gmh": "Tedesco medio alto (ca. 1050-1500)", - "goh": "Tedesco antico alto (ca. 750-1050)", - "gon": "Gondi", - "gor": "Gorontalo", - "got": "Gotico", - "grb": "Grebo", - "grc": "Greco antico (fino al 1453)", - "grn": "Guarani", - "gsw": "Tedesco (Svizzera)", - "guj": "Gujarati", + "gay": "gajo", + "gba": "Gbaya (Central African Republic)", + "gez": "gíz", + "gil": "gilberti", + "gla": "Gaelic; Scottish", + "gle": "ír", + "glg": "galíciai", + "glv": "manx", + "gmh": "German; Middle High (ca. 1050-1500)", + "goh": "német; ónémet (kb. 750-1050)", + "gon": "gondi", + "gor": "gorontalo", + "got": "gót", + "grb": "grebo", + "grc": "ógörög (1453-ig)", + "grn": "guarani", + "gsw": "German; Swiss", + "guj": "gudzsarati", "gwi": "Gwichʼin", - "hai": "Haida", - "hat": "Creolo (Haitiano)", - "hau": "Hausa", - "haw": "hawaiano", - "heb": "Ebraico", - "her": "Herero", - "hil": "Hiligayna", - "hin": "Hindi", - "hit": "hittite", + "hai": "haida", + "hat": "Creole; Haitian", + "hau": "hausza", + "haw": "hawaii", + "heb": "héber", + "her": "herero", + "hil": "hiligajnon", + "hin": "hindi", + "hit": "hettita", "hmj": "Ge", - "hmn": "Hmong", - "hmo": "Hiri motu", - "hrv": "Croato", - "hsb": "Lusaziano superiore", - "hun": "Ungherese", - "hup": "Hupa", - "hye": "armeno", - "iba": "Iban", - "ibo": "Igbo", - "ido": "Ido", + "hmn": "hmong", + "hmo": "hiri motu", + "hrv": "horvát", + "hsb": "Sorbian; Upper", + "hun": "Magyar", + "hup": "hupa", + "hye": "örmény", + "iba": "iba", + "ibo": "igbo", + "ido": "ido", "iii": "Yi; Sichuan", "iku": "inuktitut", - "ile": "Interlingua", - "ilo": "Ilocano", - "ina": "Interlingua (International Auxiliary Language Association)", - "ind": "Indonesiano", - "inh": "Ingush", - "ipk": "Inupiaq", - "isl": "Islandese", - "ita": "Italiano", - "jav": "Javanese", - "jbo": "lojban", - "jpn": "Giapponese", - "jpr": "Giudeo-persiano", - "jrb": "Giudeo-arabo", - "kaa": "Kara-Kalpak", - "kab": "Kabyle", - "kac": "Kachin", - "kal": "Kalaallisut", - "kam": "Kamba (Kenya)", - "kan": "kannada", - "kas": "kashmiri", - "kat": "Georgiano", - "kau": "Kanuri", - "kaw": "Kawi", - "kaz": "Kazako", - "kbd": "Kabardia", - "kha": "Khasi", - "khm": "Khmer centrale", - "kho": "Khotanese", - "kik": "Kikuyu", - "kin": "Kinyarwanda", - "kir": "Kirghiso", - "kmb": "Kimbundu", - "kok": "Konkani (macrolinguaggio)", - "kom": "Komi", - "kon": "Kongo", - "kor": "Coreano", - "kos": "Kosraean", - "kpe": "Kpelle", - "krc": "karachay-Balkar", - "krl": "Karelian", - "kru": "Kurukh", - "kua": "Kuanyama", + "ile": "interlingva", + "ilo": "iloko", + "ina": "interlingva (Nemzetközi Segédnyelv Egyesület)", + "ind": "indonéz", + "inh": "ingus", + "ipk": "inupiak", + "isl": "izlandi", + "ita": "olasz", + "jav": "jávai", + "jbo": "lodzsban", + "jpn": "japán", + "jpr": "judeo-perzsa", + "jrb": "judeo-arab", + "kaa": "kara-kalpak", + "kab": "kabile", + "kac": "kachin", + "kal": "Kalaallisut", + "kam": "Kamba (Kenya)", + "kan": "kannada", + "kas": "kasmíri", + "kat": "grúz", + "kau": "kanuri", + "kaw": "kawi", + "kaz": "kazah", + "kbd": "kabardi", + "kha": "kazi", + "khm": "Khmer; Central", + "kho": "kotáni", + "kik": "kikuyu", + "kin": "kinyarwanda", + "kir": "kirgiz", + "kmb": "kimbundu", + "kok": "Konkani (macrolanguage)", + "kom": "komi", + "kon": "kongo", + "kor": "koreai", + "kos": "koszrai", + "kpe": "kpelle", + "krc": "karacsai-balkar", + "krl": "kareliai", + "kru": "kuruk", + "kua": "kuanyama", "kum": "kumyk", - "kur": "Curdo", + "kur": "kurd", "kut": "kutenai", - "lad": "Ladino", - "lah": "lahnda", - "lam": "Lamba", - "lao": "Lao", - "lat": "Latino", - "lav": "Lettone", - "lez": "Lezghian", + "lad": "ladino", + "lah": "landa", + "lam": "lamba", + "lao": "lao", + "lat": "latin", + "lav": "lett", + "lez": "lezgi", "lim": "Limburgan", - "lin": "Lingala", - "lit": "Lituano", - "lol": "Mongo", + "lin": "lingala", + "lit": "litván", + "lol": "mongo", "loz": "lozi", - "ltz": "Lussemburghese", - "lua": "Luba-lulua", - "lub": "Luba-katanga", - "lug": "Ganda", - "lui": "Luiseno", - "lun": "Lunda", - "luo": "Luo (Kenya e Tanzania)", - "lus": "Lushai", - "mad": "Madurese", - "mag": "Magahi", + "ltz": "Luxembourgish", + "lua": "luba-lulua", + "lub": "luba-katanga", + "lug": "ganda", + "lui": "luisendo", + "lun": "lunda", + "luo": "luo (Kenya és Tanzánia)", + "lus": "lushai", + "mad": "maduri", + "mag": "magahi", "mah": "Marshallese", - "mai": "Maithili", - "mak": "Makasar", - "mal": "Malayalam", - "man": "Mandingo", - "mar": "Marathi", - "mas": "Masai", - "mdf": "Moksha", - "mdr": "Mandar", + "mai": "maithili", + "mak": "makasar", + "mal": "malajalam", + "man": "mandingo", + "mar": "marathi", + "mas": "maszáj", + "mdf": "moksa", + "mdr": "mandar", "men": "Mende (Sierra Leone)", - "mga": "Irlandese medio (900-1200)", + "mga": "közép-ír (900-1200)", "mic": "Mi'kmaq", - "min": "Minangkabau", - "mis": "Lingue non codificate", - "mkd": "Macedone", + "min": "minangkabau", + "mis": "Uncoded languages", + "mkd": "macedón", "mlg": "malagasy", - "mlt": "Maltese", - "mnc": "Manchu", - "mni": "Manipuri", + "mlt": "máltai", + "mnc": "manchu", + "mni": "manipuri", "moh": "mohawk", - "mon": "Mongolo", - "mos": "Mossi", - "mri": "Maori", - "msa": "Malay (macrolingua)", - "mul": "Lingue multiple", - "mus": "Creek", - "mwl": "Mirandese", - "mwr": "Marwari", - "mya": "Burmese", - "myv": "Erzya", - "nap": "Napoletano", - "nau": "Nauru", + "mon": "mongol", + "mos": "mossi", + "mri": "maori", + "msa": "Malay (macrolanguage)", + "mul": "több nyelv", + "mus": "creek", + "mwl": "mirandese", + "mwr": "marwari", + "mya": "burmai", + "myv": "erzija", + "nap": "nápolyi", + "nau": "nauru", "nav": "Navajo", - "nbl": "Ndebele del Sud", - "nde": "Ndebele del Nord", - "ndo": "Ndonga", - "nds": "Tedesco; Volgare", - "nep": "Nepali", + "nbl": "ndebele (déli)", + "nde": "ndebele (északi)", + "ndo": "ndonga", + "nds": "German; Low", + "nep": "nepáli", "new": "Bhasa; Nepal", - "nia": "Nias", - "niu": "Niuean", - "nld": "Olandese", - "nno": "Norvegese nynorsk", - "nob": "Norvegese bokmål", - "nog": "Nogai", - "non": "Norse antico", - "nor": "Norvegese", + "nia": "nias", + "niu": "niuei", + "nld": "holland", + "nno": "norvég (nynorsk)", + "nob": "Norwegian Bokmål", + "nog": "nogai", + "non": "norvég; ónorvég", + "nor": "norvég", "nqo": "N'Ko", - "nso": "Sotho settentrionale", - "nwc": "Newari antico", + "nso": "sotho (északi)", + "nwc": "newari; ónewari", "nya": "Nyanja", - "nym": "Nyamwezi", - "nyn": "Nyankole", - "nyo": "Nyoro", - "nzi": "Nzima", + "nym": "nyamwezi", + "nyn": "nyankole", + "nyo": "nyoro", + "nzi": "nzima", "oci": "Occitan (post 1500)", - "oji": "Ojibwa", - "ori": "Oriya", - "orm": "Oromo", - "osa": "Osage", + "oji": "odzsibwa", + "ori": "orija", + "orm": "oromo", + "osa": "oszage", "oss": "Ossetian", - "ota": "Turco ottomano (1500-1928)", - "pag": "Pangasinan", - "pal": "Pahlavi", + "ota": "török (ottomán) (1500-1928)", + "pag": "pangasini", + "pal": "pahlavi", "pam": "pampanga", "pan": "Panjabi", - "pap": "Papiamento", - "pau": "Palauan", - "peo": "Persiano antico (ca. 600-400 A.C.)", - "phn": "Fenicio", - "pli": "Pali", - "pol": "Polacco", - "pon": "Pohnpeian", - "por": "Portoghese", - "pro": "Provençal antico (fino al 1500)", - "pus": "Pushto", - "que": "Quechua", - "raj": "rajasthani", - "rap": "Rapanui", - "rar": "Maori (Isole Cook)", + "pap": "papiamento", + "pau": "palaui", + "peo": "Persian; Old (ca. 600-400 B.C.)", + "phn": "főníciai", + "pli": "pali", + "pol": "lengyel", + "pon": "ponpei", + "por": "portugál", + "pro": "provanszál; ó (1500-ig)", + "pus": "pushto", + "que": "kecsua", + "raj": "radzsasztani", + "rap": "rapanui", + "rar": "Maori; Cook Islands", "roh": "Romansh", - "rom": "Romany", - "ron": "Rumeno", - "run": "Rundi", - "rup": "Rumeno macedone", - "rus": "Russo", - "sad": "Sandawe", - "sag": "Sango", - "sah": "Yakut", - "sam": "Aramaico samaritano", - "san": "Sanscrito", - "sas": "Sasak", - "sat": "Santali", - "scn": "Siciliano", - "sco": "Scots", - "sel": "Selkup", - "sga": "Irlandese antico (fino al ’900)", - "shn": "Shan", - "sid": "Sidamo", - "sin": "Sinhala", - "slk": "Slovacco", - "slv": "Sloveno", - "sma": "Sami meridionale", - "sme": "Sami settentrionale", - "smj": "sami lule", + "rom": "roma", + "ron": "román", + "run": "rundi", + "rup": "Romanian; Macedo-", + "rus": "orosz", + "sad": "sandawe", + "sag": "szango", + "sah": "jakut", + "sam": "arámi; szamaritánus", + "san": "szankszrit", + "sas": "szaszak", + "sat": "szantáli", + "scn": "friuli", + "sco": "skót", + "sel": "szelkup", + "sga": "ír; óír (900-ig)", + "shn": "shan", + "sid": "szidamo", + "sin": "Sinhala", + "slk": "szlovák", + "slv": "szlovén", + "sma": "Sami; Southern", + "sme": "Sami; Northern", + "smj": "lule szami", "smn": "Sami; Inari", - "smo": "Samoano", + "smo": "szamoai", "sms": "Sami; Skolt", - "sna": "Shona", - "snd": "Sindhi", - "snk": "Soninke", - "sog": "Sogdian", - "som": "Somali", - "sot": "Sotho meridionale", - "spa": "Spagnolo", - "sqi": "Albanese", - "srd": "Sardo", + "sna": "shona", + "snd": "szindi", + "snk": "soninke", + "sog": "sogdi", + "som": "szomáli", + "sot": "sotho; déli", + "spa": "spanyol", + "sqi": "albán", + "srd": "szardíniai", "srn": "Sranan Tongo", - "srp": "Serbo", - "srr": "Serer", - "ssw": "Swati", + "srp": "szerb", + "srr": "serer", + "ssw": "swati", "suk": "sukuma", - "sun": "Sundanese", - "sus": "Susu", - "sux": "Sumero", - "swa": "Swahili (macro-lingua)", - "swe": "Svedese", - "syc": "Siriaco classico", - "syr": "Siriaco", - "tah": "Tahitian", - "tam": "Tamil", - "tat": "Tatarico", - "tel": "Telugu", - "tem": "Temne", - "ter": "Tereno", - "tet": "Tetum", - "tgk": "Tajik", - "tgl": "Tagalog", - "tha": "Thailandese", - "tig": "Tigre", - "tir": "Tigrinya", - "tiv": "Tiv", - "tkl": "Tokelau", + "sun": "szundanéz", + "sus": "susu", + "sux": "sumér", + "swa": "Swahili (macrolanguage)", + "swe": "svéd", + "syc": "Syriac; Classical", + "syr": "szír", + "tah": "tahiti", + "tam": "tamil", + "tat": "tatár", + "tel": "telugu", + "tem": "timne", + "ter": "tereno", + "tet": "tetum", + "tgk": "tadzsik", + "tgl": "tagalog", + "tha": "thai", + "tig": "tigre", + "tir": "tigrinya", + "tiv": "tiv", + "tkl": "tokelau", "tlh": "Klingon", - "tli": "Tlingit", - "tmh": "Tamashek", - "tog": "Tonga (Nyasa)", - "ton": "Tonga (Isole Tonga)", - "tpi": "Tok pisin", - "tsi": "Tsimshian", - "tsn": "Tswana", - "tso": "Tsonga", - "tuk": "Turkmeno", - "tum": "Tumbuka", - "tur": "Turco", - "tvl": "Tuvalu", - "twi": "Twi", - "tyv": "Tuvinian", - "udm": "Udmurt", - "uga": "Ugaritico", - "uig": "Uighuro", - "ukr": "Ucraino", - "umb": "Umbundu", - "und": "Non determinato", - "urd": "Urdu", - "uzb": "Usbeco", - "vai": "Vai", + "tli": "tlingit", + "tmh": "tamasek", + "tog": "tonga (nyasza)", + "ton": "tonga (Tonga-szigetek)", + "tpi": "tok pisin", + "tsi": "cimsi", + "tsn": "tswana", + "tso": "tsonga", + "tuk": "türkmén", + "tum": "tumbuka", + "tur": "török", + "tvl": "tuvalu", + "twi": "twi", + "tyv": "tuvini", + "udm": "udmurt", + "uga": "uragi", + "uig": "ujgur", + "ukr": "ukrán", + "umb": "umbundu", + "und": "ismeretlen", + "urd": "urdu", + "uzb": "üzbég", + "vai": "vai", "ven": "venda", - "vie": "Vietnamita", - "vol": "Volapük", - "vot": "Votic", + "vie": "vietnami", + "vol": "volapük", + "vot": "vót", "wal": "Wolaytta", - "war": "Waray (Filippine)", - "was": "Washo", - "wln": "Walloon", - "wol": "Wolof", + "war": "Waray (Philippines)", + "was": "washo", + "wln": "vallon", + "wol": "wolof", "xal": "Kalmyk", - "xho": "Xhosa", - "yao": "Yao", - "yap": "Yapese", - "yid": "Yiddish", - "yor": "Yoruba", - "zap": "Zapoteco", + "xho": "xhosa", + "yao": "yao", + "yap": "jap", + "yid": "jiddis", + "yor": "joruba", + "zap": "Zapoték", "zbl": "Blissymbols", - "zen": "Zenaga", - "zha": "Zhuang", - "zho": "Cinese", + "zen": "zenaga", + "zha": "zsuang", + "zho": "kínai", "zul": "Zulu", - "zun": "Zuni", - "zxx": "Nessun contenuto linguistico", + "zun": "zuni", + "zxx": "No linguistic content", "zza": "Zaza" }, - "ja": { - "aar": "アファル語", - "abk": "アブハジア語", - "ace": "アチェー語", - "ach": "アチョリ語", - "ada": "アダングメ語", + "id": { + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", + "ada": "Adangme", "ady": "Adyghe", - "afh": "アフリヒリ", - "afr": "アフリカーンス語", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Afrika", "ain": "Ainu (Japan)", - "aka": "アカン語", - "akk": "アッカド語", - "ale": "アレウト語", - "alt": "Altai; Southern", - "amh": "アムハラ語", - "ang": "English; Old (ca. 450-1100)", - "anp": "アンギカ語", - "ara": "アラビア語", - "arc": "Aramaic; Official (700-300 BCE)", - "arg": "アラゴン語", - "arn": "Mapudungun", - "arp": "アラパホー語", - "arw": "アラワク語", - "asm": "アッサム語", + "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": "アヴァル語", - "ave": "アヴェスタ語", - "awa": "アワディ語", - "aym": "アイマラ語", - "aze": "アゼルバイジャン語", - "bak": "バシキール語", - "bal": "バルーチー語", - "bam": "バンバラ語", - "ban": "バリ語", + "ava": "Avaric", + "ave": "Avestan", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Azerbaijani", + "ban": "Balinese", + "bal": "Baluchi", + "bam": "Bambara", "bas": "Basa (Cameroon)", - "bej": "ベジャ語", - "bel": "白ロシア語", + "bak": "Bashkir", + "eus": "Basque", + "bej": "Beja", + "bel": "Belarusian", "bem": "Bemba (Zambia)", - "ben": "ベンガル語", - "bho": "ボージプリー語", - "bik": "ビコル語", - "bin": "ビニ語", - "bis": "ビスラマ語", + "ben": "Bengal", "bit": "Berinomo", - "bla": "ブラックフット語", - "bod": "チベット語", - "bos": "ボスニア語", - "bra": "ブラジ語", - "bre": "ブルトン語", - "bua": "ブリヤート語", - "bug": "ブギ語", - "bul": "ブルガリア語", + "bho": "Bhojpuri", + "bik": "Bikol", "byn": "Bilin", - "cad": "カドー語", - "car": "Carib; Galibi", - "cat": "カタロニア語", - "ceb": "セブアノ語", - "ces": "チェコ語", - "cha": "チャモロ語", - "chb": "チブチャ語", - "che": "チェチェン語", - "chg": "チャガタイ語", - "chk": "チューク語", - "chm": "Mari (Russia)", - "chn": "チヌーク混成語", - "cho": "チョクトー語", - "chp": "チペワイアン語", - "chr": "チェロキー語", + "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", - "chu": "Slavonic; Old", - "chv": "チュヴァシュ語", - "chy": "シャイアン語", - "cop": "コプト語", - "cor": "コーンウォール語", - "cos": "コルシカ語", - "cre": "クリー語", - "crh": "Turkish; Crimean", - "csb": "カシュビアン語", - "cym": "ウェールズ語", - "dak": "ダコタ語", - "dan": "デンマーク語", - "dar": "ダルガン語", - "del": "デラウェア語", - "den": "スレーブ語 (アサパスカン語)", - "deu": "ドイツ語", - "dgr": "ドクリブ語", - "din": "ディンカ語", + "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)", - "dsb": "Sorbian; Lower", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Belanda", "dse": "Dutch Sign Language", - "dua": "ドゥアラ語", - "dum": "Dutch; Middle (ca. 1050-1350)", - "dyu": "デュラ語", - "dzo": "ゾンカ語", - "efi": "エフィク語", - "egy": "エジプト語 (古代)", - "eka": "エカジュク語", - "ell": "ギリシア語; 現代 (1453-)", - "elx": "エラム語", - "eng": "英語", - "enm": "英語; 中世 (1100-1500)", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Mesir Kuno", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Inggris", "enu": "Enu", - "epo": "エスペラント", - "est": "エストニア語", - "eus": "バスク語", - "ewe": "エウェ語", - "ewo": "エウォンド語", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estonia", + "ewe": "Ewe", + "ewo": "Ewondo", "fan": "Fang (Equatorial Guinea)", - "fao": "フェロー語", - "fas": "ペルシア語", - "fat": "ファンティー語", - "fij": "フィジー語", + "fat": "Fanti", + "fao": "Faro", + "fij": "Fiji", "fil": "Filipino", - "fin": "フィン語", - "fon": "フォン語", - "fra": "フランス語", - "frm": "French; Middle (ca. 1400-1600)", - "fro": "French; Old (842-ca. 1400)", - "frr": "Frisian; Northern", - "frs": "Frisian; Eastern", - "fry": "Frisian; Western", - "ful": "フラ語", - "fur": "フリウリ語", - "gaa": "ガ語", - "gay": "ガヨ語", - "gba": "Gbaya (Central African Republic)", - "gez": "ゲーズ語", - "gil": "キリバス語", - "gla": "Gaelic; Scottish", - "gle": "アイルランド語", + "fin": "Finlandia", + "fon": "Fon", + "fra": "Prancis", + "fur": "Friulian", + "ful": "Fulah", + "gaa": "Ga", "glg": "Galician", - "glv": "マン島語", - "gmh": "German; Middle High (ca. 1050-1500)", - "goh": "German; Old High (ca. 750-1050)", - "gon": "ゴーンディー語", - "gor": "ゴロンタロ語", - "got": "ゴート語", - "grb": "グレボ語", - "grc": "ギリシア語; 古代 (-1453)", - "grn": "グアラニー語", - "gsw": "German; Swiss", - "guj": "グジャラーティー語", - "gwi": "Gwichʼin", - "hai": "ハイダ語", - "hat": "Creole; Haitian", - "hau": "ハウサ語", - "haw": "ハワイ語", - "heb": "ヘブライ語", - "her": "ヘレロ語", - "hil": "ヒリジャノン語", - "hin": "ヒンディー語", - "hit": "ヒッタイト語", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", "hmj": "Ge", - "hmn": "フモング語", - "hmo": "ヒリモトゥ語", - "hrv": "クロアチア語", - "hsb": "Sorbian; Upper", - "hun": "ハンガリー語", - "hup": "アタパスカ語", - "hye": "アルメニア語", - "iba": "イバン語", - "ibo": "イボ語", - "ido": "イド語", - "iii": "Yi; Sichuan", - "iku": "イヌクチタット語", - "ile": "インターリング", - "ilo": "イロカノ語", - "ina": "インターリングア語 (国際補助語協会)", - "ind": "インドネシア語", - "inh": "イングーシ語", - "ipk": "イヌピアク語", - "isl": "アイスランド語", - "ita": "イタリア語", - "jav": "ジャワ語", - "jbo": "ロジバン語", - "jpn": "日本語", - "jpr": "ユダヤ・ペルシア語", - "jrb": "ユダヤ・アラビア語", - "kaa": "カラ・カルパク語", - "kab": "カビル語", - "kac": "カチン語", + "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": "カンナダ語", - "kas": "カシミーリー語", - "kat": "グルジア語", - "kau": "カヌリ語", - "kaw": "カウィ語", - "kaz": "カザーフ語", - "kbd": "カバルダ語", - "kha": "カシ語", - "khm": "Khmer; Central", - "kho": "ホータン語", - "kik": "キクユ語", - "kin": "キンヤルワンダ語", - "kir": "キルギス語", - "kmb": "キンブンドゥ語", + "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)", - "kom": "コミ語", - "kon": "コンゴ語", - "kor": "朝鮮語", - "kos": "コスラエ語", - "kpe": "クペレ語", - "krc": "カラチャイ・バルカル語", - "krl": "カレリア語", - "kru": "クルク語", - "kua": "クアニャマ語", - "kum": "クミック語", - "kur": "クルド語", - "kut": "クテナイ語", - "lad": "ラジノ語", - "lah": "ラフンダー語", - "lam": "ランバ語", - "lao": "ラオ語", - "lat": "ラテン語", - "lav": "ラトヴィア語", - "lez": "レズギ語", - "lim": "Limburgan", - "lin": "リンガラ語", - "lit": "リトアニア語", - "lol": "モンゴ語", - "loz": "ロジ語", - "ltz": "Luxembourgish", - "lua": "ルバ・ルルア語", - "lub": "ルバ語", - "lug": "ガンダ語", - "lui": "ルイセニョ語", - "lun": "ランダ語", - "luo": "ルオ語 (ケニアとタンザニア)", - "lus": "ルシャイ語", - "mad": "マドゥラ語", - "mag": "マガヒ語", + "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", - "mai": "マイチリ語", - "mak": "マカッサル語", - "mal": "マラヤーラム語", - "man": "マンディンゴ語", - "mar": "マラーティー語", - "mas": "マサイ語", - "mdf": "モクシャ語", - "mdr": "マンダル語", + "mwr": "Marwari", + "mas": "Masai", "men": "Mende (Sierra Leone)", - "mga": "アイルランド語; 中世 (900-1200)", "mic": "Mi'kmaq", - "min": "ミナンカバウ語", - "mis": "Uncoded languages", - "mkd": "マケドニア語", - "mlg": "マラガシ語", - "mlt": "マルタ語", - "mnc": "満州語", - "mni": "マニプル語", - "moh": "モーホーク語", - "mon": "蒙古語", - "mos": "モッシー語", - "mri": "マオリ語", - "msa": "Malay (macrolanguage)", - "mul": "多言語", - "mus": "クリーク語", - "mwl": "ミランド語", - "mwr": "マルワリ語", - "mya": "ビルマ語", - "myv": "エルジャ語", - "nap": "ナポリ語", - "nau": "ナウル語", + "min": "Minangkabau", + "mwl": "Mirandese", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Multiple languages", + "nqo": "N'Ko", + "nau": "Nauru", "nav": "Navajo", - "nbl": "ヌデベレ語; 南", - "nde": "マタベレ語; 北", - "ndo": "ンドンガ語", - "nds": "German; Low", - "nep": "ネパール語", - "new": "Bhasa; Nepal", - "nia": "ニアス語", - "niu": "ニウーエイ語", - "nld": "オランダ語", - "nno": "ニーノシュク・ノルウェー語", + "ndo": "Ndonga", + "nap": "Neapolitan", + "nia": "Nias", + "niu": "Niuean", + "zxx": "No linguistic content", + "nog": "Nogai", + "nor": "Norwegian", "nob": "Norwegian Bokmål", - "nog": "ノガイ語", - "non": "スカンジナビア語; 古期", - "nor": "ノルウェー語", - "nqo": "ンコ文字", - "nso": "Sotho; Northern", - "nwc": "Newari; Old", + "nno": "Norwegian Nynorsk", + "nym": "Nyamwezi", "nya": "Nyanja", - "nym": "ムエジ語", - "nyn": "ニャンコール語", - "nyo": "ニョロ語", - "nzi": "ンゼマ語", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", "oci": "Occitan (post 1500)", - "oji": "オジブワ語", - "ori": "オリヤー語", - "orm": "オロモ語", - "osa": "オーセージ語", + "oji": "Ojibwa", + "orm": "Oromo", + "osa": "Osage", "oss": "Ossetian", - "ota": "トルコ語; オスマン (1500-1928)", - "pag": "パンガシナーン語", - "pal": "パーラヴィー語", - "pam": "パンパンガ語", + "pal": "Pahlavi", + "pau": "Palauan", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinan", "pan": "Panjabi", - "pap": "パピアメント", - "pau": "パラオ語", - "peo": "Persian; Old (ca. 600-400 B.C.)", - "phn": "フェニキア語", - "pli": "パーリ語", - "pol": "ポーランド語", - "pon": "ポナペ語", - "por": "ポルトガル語", - "pro": "プロヴァンス語; 古期 (-1500)", - "pus": "プシュトゥー語", - "que": "キチュワ語", - "raj": "ラージャスターニー語", - "rap": "ラパヌーイ語", - "rar": "Maori; Cook Islands", + "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": "ロマニ語", - "ron": "ルーマニア語", - "run": "ルンディ語", - "rup": "Romanian; Macedo-", - "rus": "ロシア語", - "sad": "サンダウェ語", - "sag": "サンゴ語", - "sah": "ヤクート語", - "sam": "Aramaic; Samaritan", - "san": "梵語", - "sas": "ササク語", - "sat": "サンターリー語", - "scn": "シチリア語", - "sco": "スコットランド語", - "sel": "セリクプ語", - "sga": "アイルランド語; 古 (-900)", - "shn": "シャン語", - "sid": "シダモ語", - "sin": "シンハラ文字", - "slk": "スロヴァキア語", - "slv": "スロヴェニア語", - "sma": "Sami; Southern", - "sme": "Sami; Northern", - "smj": "ルレ・サーミ語", - "smn": "Sami; Inari", - "smo": "サモア語", - "sms": "Sami; Skolt", - "sna": "ショナ語", - "snd": "シンディー語", - "snk": "ソニンケ語", - "sog": "ソグド語", - "som": "ソマリ語", - "sot": "ソト語; 南", - "spa": "スペイン語", - "sqi": "アルバニア語", - "srd": "サルデーニャ語", + "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", - "srp": "セルビア語", - "srr": "セレール語", - "ssw": "シスワティ語", - "suk": "スクマ語", - "sun": "スンダ語", - "sus": "スス語", - "sux": "シュメール語", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sundan", + "sus": "Susu", "swa": "Swahili (macrolanguage)", - "swe": "スウェーデン語", - "syc": "Syriac; Classical", - "syr": "シリア語", - "tah": "タヒチ語", - "tam": "タミル語", - "tat": "タタール語", - "tel": "テルグ語", - "tem": "テムネ語", - "ter": "テレーノ語", - "tet": "テトゥン語", - "tgk": "タジク語", - "tgl": "タガログ語", - "tha": "タイ語", - "tig": "ティグレ語", - "tir": "ティグリニア語", - "tiv": "ティブ語", - "tkl": "トケラウ語", - "tlh": "Klingon", - "tli": "トリンギット語", - "tmh": "タマシェク語", - "tog": "トンガ語 (ニアサ)", - "ton": "トンガ語 (トンガ諸島)", - "tpi": "トック・ピジン", - "tsi": "チムシュ語", - "tsn": "ツワナ語", - "tso": "ツォンガ語", - "tuk": "トゥルクメン語", - "tum": "タンブカ語", - "tur": "トルコ語", - "tvl": "ツバル語", - "twi": "トウィ語", - "tyv": "ツバニア語", - "udm": "ウドムルト語", - "uga": "ウガリット語", - "uig": "ウイグル語", - "ukr": "ウクライナ語", - "umb": "アンブンドゥ語", - "und": "言語名不明", - "urd": "ウルドゥー語", - "uzb": "ウズベク語", - "vai": "ヴァイ語", - "ven": "ベンダ語", - "vie": "ベトナム語", - "vol": "ボラピューク語", - "vot": "ヴォート語", - "wal": "Wolaytta", + "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": "ワショ語", - "wln": "ワロン語", - "wol": "ウォロフ語", - "xal": "Kalmyk", - "xho": "ホサ語", - "yao": "ヤオ語", - "yap": "ヤップ語", - "yid": "イディッシュ語", - "yor": "ヨルバ語", - "zap": "ザポテック語", - "zbl": "Blissymbols", - "zen": "ゼナガ語", + "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", - "zho": "中国語", - "zul": "ズールー語", - "zun": "ズニ語", - "zxx": "No linguistic content", - "zza": "Zaza" + "zul": "Zulu", + "zun": "Zuni" }, - "km": { + "it": { "aar": "Afar", "abk": "Abkhazian", "ace": "Achinese", @@ -3801,59 +3707,59 @@ LANGUAGE_NAMES = { "ady": "Adyghe", "afh": "Afrihili", "afr": "Afrikaans", - "ain": "Ainu (Japan)", + "ain": "Ainu (Giappone)", "aka": "Akan", - "akk": "Akkadian", + "akk": "Accadico", "ale": "Aleut", - "alt": "Altai; Southern", - "amh": "Amharic", - "ang": "English; Old (ca. 450-1100)", + "alt": "Altai meridionale", + "amh": "Amarico", + "ang": "Inglese antico (ca. 450-1100)", "anp": "Angika", - "ara": "Arabic", - "arc": "Aramaic; Official (700-300 BCE)", + "ara": "Arabo", + "arc": "Aramaico ufficiale (700-300 p.e.v.)", "arg": "Aragonese", "arn": "Mapudungun", "arp": "Arapaho", "arw": "Arawak", "asm": "Assamese", - "ast": "Asturian", - "ava": "Avaric", - "ave": "Avestan", + "ast": "Asturiano", + "ava": "Avarico", + "ave": "Avestano", "awa": "Awadhi", "aym": "Aymara", - "aze": "Azerbaijani", + "aze": "Azerbaijano", "bak": "Bashkir", "bal": "Baluchi", "bam": "Bambara", "ban": "Balinese", - "bas": "Basa (Cameroon)", + "bas": "Basa (Cameru)", "bej": "Beja", - "bel": "Belarusian", + "bel": "Bielorusso", "bem": "Bemba (Zambia)", - "ben": "Bengali", + "ben": "Bengalese", "bho": "Bhojpuri", - "bik": "Bikol", + "bik": "bicol", "bin": "Bini", - "bis": "Bislama", + "bis": "bislama", "bit": "Berinomo", "bla": "Siksika", - "bod": "Tibetan", - "bos": "Bosnian", - "bra": "Braj", - "bre": "Breton", + "bod": "Tibetano", + "bos": "Bosniaco", + "bra": "braj", + "bre": "Bretone", "bua": "Buriat", "bug": "Buginese", - "bul": "Bulgarian", + "bul": "Bulgaro", "byn": "Bilin", - "cad": "Caddo", - "car": "Carib; Galibi", - "cat": "Catalan", + "cad": "caddo", + "car": "Carib (Galibi)", + "cat": "Catalano", "ceb": "Cebuano", - "ces": "Czech", + "ces": "Ceco", "cha": "Chamorro", "chb": "Chibcha", "che": "Chechen", - "chg": "Chagatai", + "chg": "Ciagataico", "chk": "Chuukese", "chm": "Mari (Russia)", "chn": "Chinook jargon", @@ -3861,167 +3767,167 @@ LANGUAGE_NAMES = { "chp": "Chipewyan", "chr": "Cherokee", "cht": "Cholón", - "chu": "Slavonic; Old", + "chu": "Slavo antico", "chv": "Chuvash", "chy": "Cheyenne", - "cop": "Coptic", + "cop": "Copto", "cor": "Cornish", - "cos": "Corsican", + "cos": "Corso", "cre": "Cree", - "crh": "Turkish; Crimean", - "csb": "Kashubian", - "cym": "Welsh", + "crh": "Turco; Crimeo", + "csb": "kashubian", + "cym": "Gallese", "dak": "Dakota", - "dan": "Danish", + "dan": "Danese", "dar": "Dargwa", - "del": "Delaware", + "del": "delaware", "den": "Slave (Athapascan)", - "deu": "German", + "deu": "Tedesco", "dgr": "Dogrib", - "din": "Dinka", + "din": "Dinca", "div": "Dhivehi", - "doi": "Dogri (macrolanguage)", - "dsb": "Sorbian; Lower", - "dse": "Dutch Sign Language", + "doi": "Dogri (macrolingua)", + "dsb": "Lusaziano inferiore", + "dse": "Olandense (linguaggio dei segni)", "dua": "Duala", - "dum": "Dutch; Middle (ca. 1050-1350)", - "dyu": "Dyula", + "dum": "Olandese medio (ca. 1050-1350)", + "dyu": "Diula", "dzo": "Dzongkha", "efi": "Efik", - "egy": "Egyptian (Ancient)", + "egy": "Egiziano antico", "eka": "Ekajuk", - "ell": "Greek; Modern (1453-)", - "elx": "Elamite", - "eng": "English", - "enm": "English; Middle (1100-1500)", + "ell": "Greco moderno (1453-)", + "elx": "Elamitico", + "eng": "Inglese", + "enm": "Inglese medio (1100-1500)", "enu": "Enu", "epo": "Esperanto", - "est": "Estonian", - "eus": "Basque", + "est": "Estone", + "eus": "Basco", "ewe": "Ewe", "ewo": "Ewondo", - "fan": "Fang (Equatorial Guinea)", + "fan": "Fang (Guinea equatoriale)", "fao": "Faroese", - "fas": "Persian", + "fas": "Persiano", "fat": "Fanti", - "fij": "Fijian", - "fil": "Filipino", - "fin": "Finnish", + "fij": "Figiano", + "fil": "Filippino", + "fin": "Finlandese", "fon": "Fon", - "fra": "French", - "frm": "French; Middle (ca. 1400-1600)", - "fro": "French; Old (842-ca. 1400)", - "frr": "Frisian; Northern", - "frs": "Frisian; Eastern", - "fry": "Frisian; Western", + "fra": "Francese", + "frm": "Francese medio (ca. 1400-1600)", + "fro": "Francese antico (842-ca. 1400)", + "frr": "Frisone settentrionale", + "frs": "Frisone orientale", + "fry": "Frisone occidentale", "ful": "Fulah", - "fur": "Friulian", - "gaa": "Ga", - "gay": "Gayo", - "gba": "Gbaya (Central African Republic)", + "fur": "Friulano", + "gaa": "ga", + "gay": "gayo", + "gba": "Gbaya (Repubblica centro africana)", "gez": "Geez", "gil": "Gilbertese", - "gla": "Gaelic; Scottish", - "gle": "Irish", - "glg": "Galician", + "gla": "Gaelico (Scozzese)", + "gle": "Gaelico", + "glg": "Galiziano", "glv": "Manx", - "gmh": "German; Middle High (ca. 1050-1500)", - "goh": "German; Old High (ca. 750-1050)", + "gmh": "Tedesco medio alto (ca. 1050-1500)", + "goh": "Tedesco antico alto (ca. 750-1050)", "gon": "Gondi", "gor": "Gorontalo", - "got": "Gothic", + "got": "Gotico", "grb": "Grebo", - "grc": "Greek; Ancient (to 1453)", + "grc": "Greco antico (fino al 1453)", "grn": "Guarani", - "gsw": "German; Swiss", + "gsw": "Tedesco (Svizzera)", "guj": "Gujarati", "gwi": "Gwichʼin", "hai": "Haida", - "hat": "Creole; Haitian", + "hat": "Creolo (Haitiano)", "hau": "Hausa", - "haw": "Hawaiian", - "heb": "Hebrew", + "haw": "hawaiano", + "heb": "Ebraico", "her": "Herero", - "hil": "Hiligaynon", + "hil": "Hiligayna", "hin": "Hindi", - "hit": "Hittite", + "hit": "hittite", "hmj": "Ge", "hmn": "Hmong", - "hmo": "Hiri Motu", - "hrv": "Croatian", - "hsb": "Sorbian; Upper", - "hun": "Hungarian", + "hmo": "Hiri motu", + "hrv": "Croato", + "hsb": "Lusaziano superiore", + "hun": "Ungherese", "hup": "Hupa", - "hye": "Armenian", + "hye": "armeno", "iba": "Iban", "ibo": "Igbo", "ido": "Ido", "iii": "Yi; Sichuan", - "iku": "Inuktitut", - "ile": "Interlingue", - "ilo": "Iloko", + "iku": "inuktitut", + "ile": "Interlingua", + "ilo": "Ilocano", "ina": "Interlingua (International Auxiliary Language Association)", - "ind": "Indonesian", + "ind": "Indonesiano", "inh": "Ingush", "ipk": "Inupiaq", - "isl": "Icelandic", - "ita": "Italian", + "isl": "Islandese", + "ita": "Italiano", "jav": "Javanese", - "jbo": "Lojban", - "jpn": "Japanese", - "jpr": "Judeo-Persian", - "jrb": "Judeo-Arabic", + "jbo": "lojban", + "jpn": "Giapponese", + "jpr": "Giudeo-persiano", + "jrb": "Giudeo-arabo", "kaa": "Kara-Kalpak", "kab": "Kabyle", "kac": "Kachin", "kal": "Kalaallisut", "kam": "Kamba (Kenya)", - "kan": "Kannada", - "kas": "Kashmiri", - "kat": "Georgian", + "kan": "kannada", + "kas": "kashmiri", + "kat": "Georgiano", "kau": "Kanuri", "kaw": "Kawi", - "kaz": "Kazakh", - "kbd": "Kabardian", + "kaz": "Kazako", + "kbd": "Kabardia", "kha": "Khasi", - "khm": "Khmer; Central", + "khm": "Khmer centrale", "kho": "Khotanese", "kik": "Kikuyu", "kin": "Kinyarwanda", - "kir": "Kirghiz", + "kir": "Kirghiso", "kmb": "Kimbundu", - "kok": "Konkani (macrolanguage)", + "kok": "Konkani (macrolinguaggio)", "kom": "Komi", "kon": "Kongo", - "kor": "Korean", + "kor": "Coreano", "kos": "Kosraean", "kpe": "Kpelle", - "krc": "Karachay-Balkar", + "krc": "karachay-Balkar", "krl": "Karelian", "kru": "Kurukh", "kua": "Kuanyama", - "kum": "Kumyk", - "kur": "Kurdish", - "kut": "Kutenai", + "kum": "kumyk", + "kur": "Curdo", + "kut": "kutenai", "lad": "Ladino", - "lah": "Lahnda", + "lah": "lahnda", "lam": "Lamba", "lao": "Lao", - "lat": "Latin", - "lav": "Latvian", + "lat": "Latino", + "lav": "Lettone", "lez": "Lezghian", "lim": "Limburgan", "lin": "Lingala", - "lit": "Lithuanian", + "lit": "Lituano", "lol": "Mongo", - "loz": "Lozi", - "ltz": "Luxembourgish", - "lua": "Luba-Lulua", - "lub": "Luba-Katanga", + "loz": "lozi", + "ltz": "Lussemburghese", + "lua": "Luba-lulua", + "lub": "Luba-katanga", "lug": "Ganda", "lui": "Luiseno", "lun": "Lunda", - "luo": "Luo (Kenya and Tanzania)", + "luo": "Luo (Kenya e Tanzania)", "lus": "Lushai", "mad": "Madurese", "mag": "Magahi", @@ -4035,46 +3941,46 @@ LANGUAGE_NAMES = { "mdf": "Moksha", "mdr": "Mandar", "men": "Mende (Sierra Leone)", - "mga": "Irish; Middle (900-1200)", + "mga": "Irlandese medio (900-1200)", "mic": "Mi'kmaq", "min": "Minangkabau", - "mis": "Uncoded languages", - "mkd": "Macedonian", - "mlg": "Malagasy", + "mis": "Lingue non codificate", + "mkd": "Macedone", + "mlg": "malagasy", "mlt": "Maltese", "mnc": "Manchu", "mni": "Manipuri", - "moh": "Mohawk", - "mon": "Mongolian", + "moh": "mohawk", + "mon": "Mongolo", "mos": "Mossi", "mri": "Maori", - "msa": "Malay (macrolanguage)", - "mul": "Multiple languages", + "msa": "Malay (macrolingua)", + "mul": "Lingue multiple", "mus": "Creek", "mwl": "Mirandese", "mwr": "Marwari", "mya": "Burmese", "myv": "Erzya", - "nap": "Neapolitan", + "nap": "Napoletano", "nau": "Nauru", "nav": "Navajo", - "nbl": "Ndebele; South", - "nde": "Ndebele; North", + "nbl": "Ndebele del Sud", + "nde": "Ndebele del Nord", "ndo": "Ndonga", - "nds": "German; Low", + "nds": "Tedesco; Volgare", "nep": "Nepali", "new": "Bhasa; Nepal", "nia": "Nias", "niu": "Niuean", - "nld": "Dutch", - "nno": "Norwegian Nynorsk", - "nob": "Norwegian Bokmål", + "nld": "Olandese", + "nno": "Norvegese nynorsk", + "nob": "Norvegese bokmål", "nog": "Nogai", - "non": "Norse; Old", - "nor": "Norwegian", + "non": "Norse antico", + "nor": "Norvegese", "nqo": "N'Ko", - "nso": "Sotho; Northern", - "nwc": "Newari; Old", + "nso": "Sotho settentrionale", + "nwc": "Newari antico", "nya": "Nyanja", "nym": "Nyamwezi", "nyn": "Nyankole", @@ -4086,84 +3992,84 @@ LANGUAGE_NAMES = { "orm": "Oromo", "osa": "Osage", "oss": "Ossetian", - "ota": "Turkish; Ottoman (1500-1928)", + "ota": "Turco ottomano (1500-1928)", "pag": "Pangasinan", "pal": "Pahlavi", - "pam": "Pampanga", + "pam": "pampanga", "pan": "Panjabi", "pap": "Papiamento", "pau": "Palauan", - "peo": "Persian; Old (ca. 600-400 B.C.)", - "phn": "Phoenician", + "peo": "Persiano antico (ca. 600-400 A.C.)", + "phn": "Fenicio", "pli": "Pali", - "pol": "Polish", + "pol": "Polacco", "pon": "Pohnpeian", - "por": "Portuguese", - "pro": "Provençal; Old (to 1500)", - "pus": "Pashto", + "por": "Portoghese", + "pro": "Provençal antico (fino al 1500)", + "pus": "Pushto", "que": "Quechua", - "raj": "Rajasthani", + "raj": "rajasthani", "rap": "Rapanui", - "rar": "Maori; Cook Islands", + "rar": "Maori (Isole Cook)", "roh": "Romansh", "rom": "Romany", - "ron": "Romanian", + "ron": "Rumeno", "run": "Rundi", - "rup": "Romanian; Macedo-", - "rus": "Russian", + "rup": "Rumeno macedone", + "rus": "Russo", "sad": "Sandawe", "sag": "Sango", "sah": "Yakut", - "sam": "Aramaic; Samaritan", - "san": "Sanskrit", + "sam": "Aramaico samaritano", + "san": "Sanscrito", "sas": "Sasak", "sat": "Santali", - "scn": "Sicilian", + "scn": "Siciliano", "sco": "Scots", "sel": "Selkup", - "sga": "Irish; Old (to 900)", + "sga": "Irlandese antico (fino al ’900)", "shn": "Shan", "sid": "Sidamo", "sin": "Sinhala", - "slk": "Slovak", - "slv": "Slovenian", - "sma": "Sami; Southern", - "sme": "Sami; Northern", - "smj": "Lule Sami", + "slk": "Slovacco", + "slv": "Sloveno", + "sma": "Sami meridionale", + "sme": "Sami settentrionale", + "smj": "sami lule", "smn": "Sami; Inari", - "smo": "Samoan", + "smo": "Samoano", "sms": "Sami; Skolt", "sna": "Shona", "snd": "Sindhi", "snk": "Soninke", "sog": "Sogdian", "som": "Somali", - "sot": "Sotho; Southern", - "spa": "Spanish", - "sqi": "Albanian", - "srd": "Sardinian", + "sot": "Sotho meridionale", + "spa": "Spagnolo", + "sqi": "Albanese", + "srd": "Sardo", "srn": "Sranan Tongo", - "srp": "Serbian", + "srp": "Serbo", "srr": "Serer", "ssw": "Swati", - "suk": "Sukuma", + "suk": "sukuma", "sun": "Sundanese", "sus": "Susu", - "sux": "Sumerian", - "swa": "Swahili (macrolanguage)", - "swe": "Swedish", - "syc": "Syriac; Classical", - "syr": "Syriac", + "sux": "Sumero", + "swa": "Swahili (macro-lingua)", + "swe": "Svedese", + "syc": "Siriaco classico", + "syr": "Siriaco", "tah": "Tahitian", "tam": "Tamil", - "tat": "Tatar", + "tat": "Tatarico", "tel": "Telugu", - "tem": "Timne", + "tem": "Temne", "ter": "Tereno", "tet": "Tetum", "tgk": "Tajik", "tgl": "Tagalog", - "tha": "Thai", + "tha": "Thailandese", "tig": "Tigre", "tir": "Tigrinya", "tiv": "Tiv", @@ -4172,32 +4078,32 @@ LANGUAGE_NAMES = { "tli": "Tlingit", "tmh": "Tamashek", "tog": "Tonga (Nyasa)", - "ton": "Tonga (Tonga Islands)", - "tpi": "Tok Pisin", + "ton": "Tonga (Isole Tonga)", + "tpi": "Tok pisin", "tsi": "Tsimshian", "tsn": "Tswana", "tso": "Tsonga", - "tuk": "Turkmen", + "tuk": "Turkmeno", "tum": "Tumbuka", - "tur": "Turkish", + "tur": "Turco", "tvl": "Tuvalu", "twi": "Twi", "tyv": "Tuvinian", "udm": "Udmurt", - "uga": "Ugaritic", - "uig": "Uighur", - "ukr": "Ukrainian", + "uga": "Ugaritico", + "uig": "Uighuro", + "ukr": "Ucraino", "umb": "Umbundu", - "und": "Undetermined", + "und": "Non determinato", "urd": "Urdu", - "uzb": "Uzbek", + "uzb": "Usbeco", "vai": "Vai", - "ven": "Venda", - "vie": "Vietnamese", + "ven": "venda", + "vie": "Vietnamita", "vol": "Volapük", "vot": "Votic", "wal": "Wolaytta", - "war": "Waray (Philippines)", + "war": "Waray (Filippine)", "was": "Washo", "wln": "Walloon", "wol": "Wolof", @@ -4207,1062 +4113,2290 @@ LANGUAGE_NAMES = { "yap": "Yapese", "yid": "Yiddish", "yor": "Yoruba", - "zap": "Zapotec", + "zap": "Zapoteco", "zbl": "Blissymbols", "zen": "Zenaga", "zha": "Zhuang", - "zho": "Chinese", + "zho": "Cinese", "zul": "Zulu", "zun": "Zuni", - "zxx": "No linguistic content", + "zxx": "Nessun contenuto linguistico", "zza": "Zaza" }, - "ko": { - "abk": "압하스어", - "ace": "아체어", - "ach": "아촐리어", - "ada": "Adangme", + "ja": { + "aar": "アファル語", + "abk": "アブハジア語", + "ace": "アチェー語", + "ach": "アチョリ語", + "ada": "アダングメ語", "ady": "Adyghe", - "aar": "아파르어", - "afh": "Afrihili", - "afr": "아프리칸스어", + "afh": "アフリヒリ", + "afr": "アフリカーンス語", "ain": "Ainu (Japan)", - "aka": "Akan", - "akk": "Akkadian", - "sqi": "Albanian", - "ale": "Aleut", - "amh": "Amharic", - "anp": "Angika", - "ara": "아라비아어", - "arg": "Aragonese", - "arp": "Arapaho", - "arw": "Arawak", - "hye": "아르메니아어", - "asm": "Assamese", + "aka": "アカン語", + "akk": "アッカド語", + "ale": "アレウト語", + "alt": "Altai; Southern", + "amh": "アムハラ語", + "ang": "English; Old (ca. 450-1100)", + "anp": "アンギカ語", + "ara": "アラビア語", + "arc": "Aramaic; Official (700-300 BCE)", + "arg": "アラゴン語", + "arn": "Mapudungun", + "arp": "アラパホー語", + "arw": "アラワク語", + "asm": "アッサム語", "ast": "Asturian", - "ava": "Avaric", - "ave": "아베스타어", - "awa": "Awadhi", - "aym": "Aymara", - "aze": "Azerbaijani", - "ban": "발리 문자", - "bal": "Baluchi", - "bam": "Bambara", - "bas": "Basa (Cameroon)", - "bak": "Bashkir", - "eus": "바스크어", - "bej": "Beja", - "bel": "벨로루시어", + "ava": "アヴァル語", + "ave": "アヴェスタ語", + "awa": "アワディ語", + "aym": "アイマラ語", + "aze": "アゼルバイジャン語", + "bak": "バシキール語", + "bal": "バルーチー語", + "bam": "バンバラ語", + "ban": "バリ語", + "bas": "Basa (Cameroon)", + "bej": "ベジャ語", + "bel": "白ロシア語", "bem": "Bemba (Zambia)", - "ben": "벵골 문자", + "ben": "ベンガル語", + "bho": "ボージプリー語", + "bik": "ビコル語", + "bin": "ビニ語", + "bis": "ビスラマ語", "bit": "Berinomo", - "bho": "Bhojpuri", - "bik": "Bikol", + "bla": "ブラックフット語", + "bod": "チベット語", + "bos": "ボスニア語", + "bra": "ブラジ語", + "bre": "ブルトン語", + "bua": "ブリヤート語", + "bug": "ブギ語", + "bul": "ブルガリア語", "byn": "Bilin", - "bin": "Bini", - "bis": "Bislama", - "zbl": "Blissymbols", - "bos": "Bosnian", - "bra": "Braj", - "bre": "Breton", - "bug": "부기 문자", - "bul": "불가리아어", - "bua": "Buriat", - "mya": "Burmese", - "cad": "Caddo", - "cat": "카탈로니아어", - "ceb": "Cebuano", - "chg": "Chagatai", - "cha": "Chamorro", - "che": "Chechen", - "chr": "체로키 문자", - "chy": "Cheyenne", - "chb": "Chibcha", - "zho": "중국어", - "chn": "Chinook jargon", - "chp": "Chipewyan", - "cho": "Choctaw", + "cad": "カドー語", + "car": "Carib; Galibi", + "cat": "カタロニア語", + "ceb": "セブアノ語", + "ces": "チェコ語", + "cha": "チャモロ語", + "chb": "チブチャ語", + "che": "チェチェン語", + "chg": "チャガタイ語", + "chk": "チューク語", + "chm": "Mari (Russia)", + "chn": "チヌーク混成語", + "cho": "チョクトー語", + "chp": "チペワイアン語", + "chr": "チェロキー語", "cht": "Cholón", - "chk": "Chuukese", - "chv": "Chuvash", - "cop": "콥트어", - "cor": "Cornish", - "cos": "Corsican", - "cre": "Cree", - "mus": "Creek", - "hrv": "크로아티아어", - "ces": "체크어", - "dak": "Dakota", - "dan": "덴마크어", - "dar": "Dargwa", - "del": "Delaware", + "chu": "Slavonic; Old", + "chv": "チュヴァシュ語", + "chy": "シャイアン語", + "cop": "コプト語", + "cor": "コーンウォール語", + "cos": "コルシカ語", + "cre": "クリー語", + "crh": "Turkish; Crimean", + "csb": "カシュビアン語", + "cym": "ウェールズ語", + "dak": "ダコタ語", + "dan": "デンマーク語", + "dar": "ダルガン語", + "del": "デラウェア語", + "den": "スレーブ語 (アサパスカン語)", + "deu": "ドイツ語", + "dgr": "ドクリブ語", + "din": "ディンカ語", "div": "Dhivehi", - "din": "Dinka", "doi": "Dogri (macrolanguage)", - "dgr": "Dogrib", - "dua": "Duala", - "nld": "네덜란드어", + "dsb": "Sorbian; Lower", "dse": "Dutch Sign Language", - "dyu": "Dyula", - "dzo": "Dzongkha", - "efi": "Efik", - "egy": "Egyptian (Ancient)", - "eka": "Ekajuk", - "elx": "Elamite", - "eng": "영어", + "dua": "ドゥアラ語", + "dum": "Dutch; Middle (ca. 1050-1350)", + "dyu": "デュラ語", + "dzo": "ゾンカ語", + "efi": "エフィク語", + "egy": "エジプト語 (古代)", + "eka": "エカジュク語", + "ell": "ギリシア語; 現代 (1453-)", + "elx": "エラム語", + "eng": "英語", + "enm": "英語; 中世 (1100-1500)", "enu": "Enu", - "myv": "Erzya", - "epo": "에스페란토어", - "est": "에스토니아어", - "ewe": "Ewe", - "ewo": "Ewondo", + "epo": "エスペラント", + "est": "エストニア語", + "eus": "バスク語", + "ewe": "エウェ語", + "ewo": "エウォンド語", "fan": "Fang (Equatorial Guinea)", - "fat": "Fanti", - "fao": "페로스어", - "fij": "Fijian", + "fao": "フェロー語", + "fas": "ペルシア語", + "fat": "ファンティー語", + "fij": "フィジー語", "fil": "Filipino", - "fin": "핀란드어", - "fon": "Fon", - "fra": "프랑스어", - "fur": "Friulian", - "ful": "Fulah", - "gaa": "Ga", - "glg": "Galician", - "lug": "Ganda", - "gay": "Gayo", + "fin": "フィン語", + "fon": "フォン語", + "fra": "フランス語", + "frm": "French; Middle (ca. 1400-1600)", + "fro": "French; Old (842-ca. 1400)", + "frr": "Frisian; Northern", + "frs": "Frisian; Eastern", + "fry": "Frisian; Western", + "ful": "フラ語", + "fur": "フリウリ語", + "gaa": "ガ語", + "gay": "ガヨ語", "gba": "Gbaya (Central African Republic)", - "hmj": "Ge", - "gez": "Geez", - "kat": "그루지야어", - "deu": "독일어", - "gil": "Gilbertese", - "gon": "Gondi", - "gor": "Gorontalo", - "got": "고트어", - "grb": "Grebo", - "grn": "Guarani", - "guj": "구자라트 문자", + "gez": "ゲーズ語", + "gil": "キリバス語", + "gla": "Gaelic; Scottish", + "gle": "アイルランド語", + "glg": "Galician", + "glv": "マン島語", + "gmh": "German; Middle High (ca. 1050-1500)", + "goh": "German; Old High (ca. 750-1050)", + "gon": "ゴーンディー語", + "gor": "ゴロンタロ語", + "got": "ゴート語", + "grb": "グレボ語", + "grc": "ギリシア語; 古代 (-1453)", + "grn": "グアラニー語", + "gsw": "German; Swiss", + "guj": "グジャラーティー語", "gwi": "Gwichʼin", - "hai": "Haida", - "hau": "Hausa", - "haw": "Hawaiian", - "heb": "헤브루어", - "her": "Herero", - "hil": "Hiligaynon", - "hin": "Hindi", - "hmo": "Hiri Motu", - "hit": "Hittite", - "hmn": "Hmong", - "hun": "헝가리어", - "hup": "Hupa", - "iba": "Iban", - "isl": "아이슬란드어", - "ido": "Ido", - "ibo": "Igbo", - "ilo": "Iloko", - "ind": "인도네시아어", - "inh": "Ingush", - "ina": "Interlingua (International Auxiliary Language Association)", - "ile": "Interlingue", - "iku": "Inuktitut", - "ipk": "Inupiaq", - "gle": "아일랜드어", - "ita": "이탈리아어", - "jpn": "일본어", - "jav": "Javanese", - "jrb": "Judeo-Arabic", - "jpr": "Judeo-Persian", - "kbd": "Kabardian", - "kab": "Kabyle", - "kac": "Kachin", - "kal": "Kalaallisut", - "xal": "Kalmyk", - "kam": "Kamba (Kenya)", - "kan": " 칸나다 문자", - "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": "한국어", - "kos": "Kosraean", - "kpe": "Kpelle", - "kua": "Kuanyama", - "kum": "Kumyk", - "kur": "Kurdish", - "kru": "Kurukh", - "kut": "Kutenai", - "lad": "Ladino", - "lah": "Lahnda", - "lam": "Lamba", - "lao": "라오 문자", - "lat": "Latin", - "lav": "라트비아어", - "lez": "Lezghian", + "hai": "ハイダ語", + "hat": "Creole; Haitian", + "hau": "ハウサ語", + "haw": "ハワイ語", + "heb": "ヘブライ語", + "her": "ヘレロ語", + "hil": "ヒリジャノン語", + "hin": "ヒンディー語", + "hit": "ヒッタイト語", + "hmj": "Ge", + "hmn": "フモング語", + "hmo": "ヒリモトゥ語", + "hrv": "クロアチア語", + "hsb": "Sorbian; Upper", + "hun": "ハンガリー語", + "hup": "アタパスカ語", + "hye": "アルメニア語", + "iba": "イバン語", + "ibo": "イボ語", + "ido": "イド語", + "iii": "Yi; Sichuan", + "iku": "イヌクチタット語", + "ile": "インターリング", + "ilo": "イロカノ語", + "ina": "インターリングア語 (国際補助語協会)", + "ind": "インドネシア語", + "inh": "イングーシ語", + "ipk": "イヌピアク語", + "isl": "アイスランド語", + "ita": "イタリア語", + "jav": "ジャワ語", + "jbo": "ロジバン語", + "jpn": "日本語", + "jpr": "ユダヤ・ペルシア語", + "jrb": "ユダヤ・アラビア語", + "kaa": "カラ・カルパク語", + "kab": "カビル語", + "kac": "カチン語", + "kal": "Kalaallisut", + "kam": "Kamba (Kenya)", + "kan": "カンナダ語", + "kas": "カシミーリー語", + "kat": "グルジア語", + "kau": "カヌリ語", + "kaw": "カウィ語", + "kaz": "カザーフ語", + "kbd": "カバルダ語", + "kha": "カシ語", + "khm": "Khmer; Central", + "kho": "ホータン語", + "kik": "キクユ語", + "kin": "キンヤルワンダ語", + "kir": "キルギス語", + "kmb": "キンブンドゥ語", + "kok": "Konkani (macrolanguage)", + "kom": "コミ語", + "kon": "コンゴ語", + "kor": "朝鮮語", + "kos": "コスラエ語", + "kpe": "クペレ語", + "krc": "カラチャイ・バルカル語", + "krl": "カレリア語", + "kru": "クルク語", + "kua": "クアニャマ語", + "kum": "クミック語", + "kur": "クルド語", + "kut": "クテナイ語", + "lad": "ラジノ語", + "lah": "ラフンダー語", + "lam": "ランバ語", + "lao": "ラオ語", + "lat": "ラテン語", + "lav": "ラトヴィア語", + "lez": "レズギ語", "lim": "Limburgan", - "lin": "Lingala", - "lit": "리투아니아어", - "jbo": "Lojban", - "loz": "Lozi", - "lub": "Luba-Katanga", - "lua": "Luba-Lulua", - "lui": "Luiseno", - "smj": "Lule Sami", - "lun": "Lunda", - "luo": "Luo (Kenya and Tanzania)", - "lus": "Lushai", + "lin": "リンガラ語", + "lit": "リトアニア語", + "lol": "モンゴ語", + "loz": "ロジ語", "ltz": "Luxembourgish", - "mkd": "마케도니아어", - "mad": "Madurese", - "mag": "Magahi", - "mai": "Maithili", - "mak": "Makasar", - "mlg": "Malagasy", - "msa": "Malay (macrolanguage)", - "mal": "말라얄람 문자", - "mlt": "Maltese", - "mnc": "Manchu", - "mdr": "Mandar", - "man": "Mandingo", - "mni": "Manipuri", - "glv": "Manx", - "mri": "Maori", - "arn": "Mapudungun", - "mar": "Marathi", - "chm": "Mari (Russia)", + "lua": "ルバ・ルルア語", + "lub": "ルバ語", + "lug": "ガンダ語", + "lui": "ルイセニョ語", + "lun": "ランダ語", + "luo": "ルオ語 (ケニアとタンザニア)", + "lus": "ルシャイ語", + "mad": "マドゥラ語", + "mag": "マガヒ語", "mah": "Marshallese", - "mwr": "Marwari", - "mas": "Masai", + "mai": "マイチリ語", + "mak": "マカッサル語", + "mal": "マラヤーラム語", + "man": "マンディンゴ語", + "mar": "マラーティー語", + "mas": "マサイ語", + "mdf": "モクシャ語", + "mdr": "マンダル語", "men": "Mende (Sierra Leone)", + "mga": "アイルランド語; 中世 (900-1200)", "mic": "Mi'kmaq", - "min": "Minangkabau", - "mwl": "Mirandese", - "moh": "Mohawk", - "mdf": "Moksha", - "lol": "Mongo", - "mon": "몽골 문자", - "mos": "Mossi", - "mul": "Multiple languages", - "nqo": "응코 문자", - "nau": "나우루어", - "nav": "나바호어", - "ndo": "Ndonga", - "nap": "Neapolitan", - "nia": "Nias", - "niu": "Niuean", - "zxx": "No linguistic content", - "nog": "Nogai", - "nor": "노르웨이어", + "min": "ミナンカバウ語", + "mis": "Uncoded languages", + "mkd": "マケドニア語", + "mlg": "マラガシ語", + "mlt": "マルタ語", + "mnc": "満州語", + "mni": "マニプル語", + "moh": "モーホーク語", + "mon": "蒙古語", + "mos": "モッシー語", + "mri": "マオリ語", + "msa": "Malay (macrolanguage)", + "mul": "多言語", + "mus": "クリーク語", + "mwl": "ミランド語", + "mwr": "マルワリ語", + "mya": "ビルマ語", + "myv": "エルジャ語", + "nap": "ナポリ語", + "nau": "ナウル語", + "nav": "Navajo", + "nbl": "ヌデベレ語; 南", + "nde": "マタベレ語; 北", + "ndo": "ンドンガ語", + "nds": "German; Low", + "nep": "ネパール語", + "new": "Bhasa; Nepal", + "nia": "ニアス語", + "niu": "ニウーエイ語", + "nld": "オランダ語", + "nno": "ニーノシュク・ノルウェー語", "nob": "Norwegian Bokmål", - "nno": "Norwegian Nynorsk", - "nym": "Nyamwezi", + "nog": "ノガイ語", + "non": "スカンジナビア語; 古期", + "nor": "ノルウェー語", + "nqo": "ンコ文字", + "nso": "Sotho; Northern", + "nwc": "Newari; Old", "nya": "Nyanja", - "nyn": "Nyankole", - "nyo": "Nyoro", - "nzi": "Nzima", + "nym": "ムエジ語", + "nyn": "ニャンコール語", + "nyo": "ニョロ語", + "nzi": "ンゼマ語", "oci": "Occitan (post 1500)", - "oji": "Ojibwa", - "orm": "Oromo", - "osa": "Osage", + "oji": "オジブワ語", + "ori": "オリヤー語", + "orm": "オロモ語", + "osa": "オーセージ語", "oss": "Ossetian", - "pal": "Pahlavi", - "pau": "Palauan", - "pli": "Pali", - "pam": "Pampanga", - "pag": "Pangasinan", + "ota": "トルコ語; オスマン (1500-1928)", + "pag": "パンガシナーン語", + "pal": "パーラヴィー語", + "pam": "パンパンガ語", "pan": "Panjabi", - "pap": "Papiamento", - "fas": "Persian", - "phn": " 페니키아 문자", - "pon": "Pohnpeian", - "pol": "폴란드어", - "por": "포르투갈어", - "pus": "Pashto", - "que": "Quechua", - "raj": "Rajasthani", - "rap": "Rapanui", - "ron": "루마니아어", + "pap": "パピアメント", + "pau": "パラオ語", + "peo": "Persian; Old (ca. 600-400 B.C.)", + "phn": "フェニキア語", + "pli": "パーリ語", + "pol": "ポーランド語", + "pon": "ポナペ語", + "por": "ポルトガル語", + "pro": "プロヴァンス語; 古期 (-1500)", + "pus": "プシュトゥー語", + "que": "キチュワ語", + "raj": "ラージャスターニー語", + "rap": "ラパヌーイ語", + "rar": "Maori; Cook Islands", "roh": "Romansh", - "rom": "Romany", - "run": "Rundi", - "rus": "러시아어", - "smo": "Samoan", - "sad": "Sandawe", - "sag": "Sango", - "san": "Sanskrit", - "sat": "Santali", - "srd": "Sardinian", - "sas": "Sasak", - "sco": "Scots", - "sel": "Selkup", - "srp": "세르비아어", - "srr": "Serer", - "shn": "Shan", - "sna": "Shona", - "scn": "Sicilian", - "sid": "Sidamo", - "bla": "Siksika", - "snd": "Sindhi", - "sin": "싱할라 문자", - "den": "Slave (Athapascan)", - "slk": "슬로바키아어", - "slv": "슬로베니아어", - "sog": "Sogdian", - "som": "Somali", - "snk": "Soninke", - "spa": "스페인어", + "rom": "ロマニ語", + "ron": "ルーマニア語", + "run": "ルンディ語", + "rup": "Romanian; Macedo-", + "rus": "ロシア語", + "sad": "サンダウェ語", + "sag": "サンゴ語", + "sah": "ヤクート語", + "sam": "Aramaic; Samaritan", + "san": "梵語", + "sas": "ササク語", + "sat": "サンターリー語", + "scn": "シチリア語", + "sco": "スコットランド語", + "sel": "セリクプ語", + "sga": "アイルランド語; 古 (-900)", + "shn": "シャン語", + "sid": "シダモ語", + "sin": "シンハラ文字", + "slk": "スロヴァキア語", + "slv": "スロヴェニア語", + "sma": "Sami; Southern", + "sme": "Sami; Northern", + "smj": "ルレ・サーミ語", + "smn": "Sami; Inari", + "smo": "サモア語", + "sms": "Sami; Skolt", + "sna": "ショナ語", + "snd": "シンディー語", + "snk": "ソニンケ語", + "sog": "ソグド語", + "som": "ソマリ語", + "sot": "ソト語; 南", + "spa": "スペイン語", + "sqi": "アルバニア語", + "srd": "サルデーニャ語", "srn": "Sranan Tongo", - "suk": "Sukuma", - "sux": "Sumerian", - "sun": "Sundanese", - "sus": "Susu", + "srp": "セルビア語", + "srr": "セレール語", + "ssw": "シスワティ語", + "suk": "スクマ語", + "sun": "スンダ語", + "sus": "スス語", + "sux": "シュメール語", "swa": "Swahili (macrolanguage)", - "ssw": "Swati", - "swe": "스웨덴어", - "syr": "시리아 문자", - "tgl": "타갈로그 문자", - "tah": "Tahitian", - "tgk": "Tajik", - "tmh": "Tamashek", - "tam": "타밀 문자", - "tat": "Tatar", - "tel": "텔루구 문자", - "ter": "Tereno", - "tet": "Tetum", - "tha": "태국어", - "bod": "티베트 문자", - "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": "터키어", - "tuk": "Turkmen", - "tvl": "Tuvalu", - "tyv": "Tuvinian", - "twi": "Twi", - "udm": "Udmurt", - "uga": "우가리트 문자", - "uig": "Uighur", - "ukr": "Ukrainian", - "umb": "Umbundu", - "mis": "Uncoded languages", - "und": "Undetermined", - "urd": "Urdu", - "uzb": "Uzbek", - "vai": "Vai", - "ven": "Venda", - "vie": "베트남어", - "vol": "Volapük", - "vot": "Votic", - "wln": "Walloon", - "war": "Waray (Philippines)", - "was": "Washo", - "cym": "Welsh", + "swe": "スウェーデン語", + "syc": "Syriac; Classical", + "syr": "シリア語", + "tah": "タヒチ語", + "tam": "タミル語", + "tat": "タタール語", + "tel": "テルグ語", + "tem": "テムネ語", + "ter": "テレーノ語", + "tet": "テトゥン語", + "tgk": "タジク語", + "tgl": "タガログ語", + "tha": "タイ語", + "tig": "ティグレ語", + "tir": "ティグリニア語", + "tiv": "ティブ語", + "tkl": "トケラウ語", + "tlh": "Klingon", + "tli": "トリンギット語", + "tmh": "タマシェク語", + "tog": "トンガ語 (ニアサ)", + "ton": "トンガ語 (トンガ諸島)", + "tpi": "トック・ピジン", + "tsi": "チムシュ語", + "tsn": "ツワナ語", + "tso": "ツォンガ語", + "tuk": "トゥルクメン語", + "tum": "タンブカ語", + "tur": "トルコ語", + "tvl": "ツバル語", + "twi": "トウィ語", + "tyv": "ツバニア語", + "udm": "ウドムルト語", + "uga": "ウガリット語", + "uig": "ウイグル語", + "ukr": "ウクライナ語", + "umb": "アンブンドゥ語", + "und": "言語名不明", + "urd": "ウルドゥー語", + "uzb": "ウズベク語", + "vai": "ヴァイ語", + "ven": "ベンダ語", + "vie": "ベトナム語", + "vol": "ボラピューク語", + "vot": "ヴォート語", "wal": "Wolaytta", - "wol": "Wolof", - "xho": "Xhosa", - "sah": "Yakut", - "yao": "Yao", - "yap": "Yapese", - "yid": "Yiddish", - "yor": "Yoruba", - "zap": "Zapotec", - "zza": "Zaza", - "zen": "Zenaga", + "war": "Waray (Philippines)", + "was": "ワショ語", + "wln": "ワロン語", + "wol": "ウォロフ語", + "xal": "Kalmyk", + "xho": "ホサ語", + "yao": "ヤオ語", + "yap": "ヤップ語", + "yid": "イディッシュ語", + "yor": "ヨルバ語", + "zap": "ザポテック語", + "zbl": "Blissymbols", + "zen": "ゼナガ語", "zha": "Zhuang", - "zul": "Zulu", - "zun": "Zuni" + "zho": "中国語", + "zul": "ズールー語", + "zun": "ズニ語", + "zxx": "No linguistic content", + "zza": "Zaza" }, - "nl": { - "aar": "Afar; Hamitisch", - "abk": "Abchazisch", - "ace": "Achinees", - "ach": "Acholi", + "km": { + "aar": "Afar", + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", "ada": "Adangme", "ady": "Adyghe", "afh": "Afrihili", "afr": "Afrikaans", "ain": "Ainu (Japan)", - "aka": "Akaans", - "akk": "Akkadiaans", + "aka": "Akan", + "akk": "Akkadian", "ale": "Aleut", - "alt": "Altajs; zuidelijk", - "amh": "Amhaars; Amharisch", - "ang": "Engels; oud (ca. 450-1100)", + "alt": "Altai; Southern", + "amh": "Amharic", + "ang": "English; Old (ca. 450-1100)", "anp": "Angika", - "ara": "Arabisch", - "arc": "Aramees; officieel (700-300 B.C.)", - "arg": "Aragonees", + "ara": "Arabic", + "arc": "Aramaic; Official (700-300 BCE)", + "arg": "Aragonese", "arn": "Mapudungun", "arp": "Arapaho", "arw": "Arawak", - "asm": "Assamees; Assami", - "ast": "Asturisch", - "ava": "Avaars; Awari", - "ave": "Avestisch", + "asm": "Assamese", + "ast": "Asturian", + "ava": "Avaric", + "ave": "Avestan", "awa": "Awadhi", "aym": "Aymara", - "aze": "Azerbeidzjaans", - "bak": "Basjkiers; Basjkirisch", - "bal": "Balutsji; Baluchi", + "aze": "Azerbaijani", + "bak": "Bashkir", + "bal": "Baluchi", "bam": "Bambara", - "ban": "Balinees", - "bas": "Basa (Kameroen)", + "ban": "Balinese", + "bas": "Basa (Cameroon)", "bej": "Beja", - "bel": "Wit-Russisch; Belarussisch", + "bel": "Belarusian", "bem": "Bemba (Zambia)", - "ben": "Bengaals", + "ben": "Bengali", "bho": "Bhojpuri", "bik": "Bikol", - "bin": "Bini; Edo", + "bin": "Bini", "bis": "Bislama", "bit": "Berinomo", "bla": "Siksika", - "bod": "Tibetaans", - "bos": "Bosnisch", + "bod": "Tibetan", + "bos": "Bosnian", "bra": "Braj", - "bre": "Bretons; Bretoens", - "bua": "Boeriaats", - "bug": "Buginees", - "bul": "Bulgaars", + "bre": "Breton", + "bua": "Buriat", + "bug": "Buginese", + "bul": "Bulgarian", "byn": "Bilin", "cad": "Caddo", - "car": "Caribische talen", - "cat": "Catalaans", + "car": "Carib; Galibi", + "cat": "Catalan", "ceb": "Cebuano", - "ces": "Tsjechisch", + "ces": "Czech", "cha": "Chamorro", - "chb": "Tsjibtsja", - "che": "Tsjetsjeens", + "chb": "Chibcha", + "che": "Chechen", "chg": "Chagatai", - "chk": "Chukees", - "chm": "Mari (Rusland)", - "chn": "Chinook-jargon", + "chk": "Chuukese", + "chm": "Mari (Russia)", + "chn": "Chinook jargon", "cho": "Choctaw", - "chp": "Chipewyaans", + "chp": "Chipewyan", "chr": "Cherokee", "cht": "Cholón", - "chu": "Slavisch; oud (kerk)", - "chv": "Tsjoevasjisch", + "chu": "Slavonic; Old", + "chv": "Chuvash", "chy": "Cheyenne", - "cop": "Koptisch", - "cor": "Cornisch", - "cos": "Corsicaans", + "cop": "Coptic", + "cor": "Cornish", + "cos": "Corsican", "cre": "Cree", - "crh": "Turks; Crimean", - "csb": "Kasjoebiaans", + "crh": "Turkish; Crimean", + "csb": "Kashubian", "cym": "Welsh", "dak": "Dakota", - "dan": "Deens", + "dan": "Danish", "dar": "Dargwa", "del": "Delaware", - "den": "Slavisch (Athapascaans)", - "deu": "Duits", + "den": "Slave (Athapascan)", + "deu": "German", "dgr": "Dogrib", "din": "Dinka", - "div": "Divehi", - "doi": "Dogri", - "dsb": "Sorbisch; lager", - "dse": "Nederlandse gebarentaal", + "div": "Dhivehi", + "doi": "Dogri (macrolanguage)", + "dsb": "Sorbian; Lower", + "dse": "Dutch Sign Language", "dua": "Duala", - "dum": "Nederlands; middel (ca. 1050-1350)", + "dum": "Dutch; Middle (ca. 1050-1350)", "dyu": "Dyula", "dzo": "Dzongkha", - "efi": "Efikisch", - "egy": "Egyptisch (antiek)", + "efi": "Efik", + "egy": "Egyptian (Ancient)", "eka": "Ekajuk", - "ell": "Grieks; Modern (1453-)", - "elx": "Elamitisch", - "eng": "Engels", - "enm": "Engels; middel (1100-1500)", + "ell": "Greek; Modern (1453-)", + "elx": "Elamite", + "eng": "English", + "enm": "English; Middle (1100-1500)", "enu": "Enu", "epo": "Esperanto", - "est": "Estlands", - "eus": "Baskisch", + "est": "Estonian", + "eus": "Basque", "ewe": "Ewe", "ewo": "Ewondo", - "fan": "Fang", - "fao": "Faeröers", - "fas": "Perzisch", + "fan": "Fang (Equatorial Guinea)", + "fao": "Faroese", + "fas": "Persian", "fat": "Fanti", - "fij": "Fijisch", - "fil": "Filipijns", - "fin": "Fins", + "fij": "Fijian", + "fil": "Filipino", + "fin": "Finnish", "fon": "Fon", - "fra": "Frans", - "frm": "Frans; middel (ca. 1400-1600)", - "fro": "Frans; oud (842-ca. 1400)", - "frr": "Fries; noordelijk (Duitsland)", - "frs": "Fries; oostelijk (Duitsland)", - "fry": "Fries", + "fra": "French", + "frm": "French; Middle (ca. 1400-1600)", + "fro": "French; Old (842-ca. 1400)", + "frr": "Frisian; Northern", + "frs": "Frisian; Eastern", + "fry": "Frisian; Western", "ful": "Fulah", - "fur": "Friulisch", + "fur": "Friulian", "gaa": "Ga", "gay": "Gayo", - "gba": "Gbaya (Centraal Afrikaanse Republiek)", - "gez": "Ge'ez", - "gil": "Gilbertees", - "gla": "Keltisch; schots", - "gle": "Iers", - "glg": "Galiciaans", + "gba": "Gbaya (Central African Republic)", + "gez": "Geez", + "gil": "Gilbertese", + "gla": "Gaelic; Scottish", + "gle": "Irish", + "glg": "Galician", "glv": "Manx", - "gmh": "Duits; middel hoog (ca. 1050-1500)", - "goh": "Duits; oud hoog (ca. 750-1050)", + "gmh": "German; Middle High (ca. 1050-1500)", + "goh": "German; Old High (ca. 750-1050)", "gon": "Gondi", "gor": "Gorontalo", - "got": "Gothisch", + "got": "Gothic", "grb": "Grebo", - "grc": "Grieks; antiek (tot 1453)", + "grc": "Greek; Ancient (to 1453)", "grn": "Guarani", - "gsw": "Duits; Zwitserland", + "gsw": "German; Swiss", "guj": "Gujarati", "gwi": "Gwichʼin", "hai": "Haida", - "hat": "Creools; Haïtiaans", + "hat": "Creole; Haitian", "hau": "Hausa", - "haw": "Hawaiiaans", - "heb": "Hebreeuws", + "haw": "Hawaiian", + "heb": "Hebrew", "her": "Herero", - "hil": "Hiligainoons", + "hil": "Hiligaynon", "hin": "Hindi", - "hit": "Hittitisch", + "hit": "Hittite", "hmj": "Ge", "hmn": "Hmong", "hmo": "Hiri Motu", - "hrv": "Kroatisch", - "hsb": "Servisch; hoger", - "hun": "Hongaars", + "hrv": "Croatian", + "hsb": "Sorbian; Upper", + "hun": "Hungarian", "hup": "Hupa", - "hye": "Armeens", - "iba": "Ibaans", + "hye": "Armenian", + "iba": "Iban", "ibo": "Igbo", "ido": "Ido", - "iii": "Yi; Sichuan - Nuosu", + "iii": "Yi; Sichuan", "iku": "Inuktitut", "ile": "Interlingue", "ilo": "Iloko", "ina": "Interlingua (International Auxiliary Language Association)", - "ind": "Indonesisch", - "inh": "Ingoesjetisch", - "ipk": "Inupiak", - "isl": "IJslands", - "ita": "Italiaans", - "jav": "Javaans", - "jbo": "Lojbaans", - "jpn": "Japans", - "jpr": "Joods-Perzisch", - "jrb": "Joods-Arabisch", + "ind": "Indonesian", + "inh": "Ingush", + "ipk": "Inupiaq", + "isl": "Icelandic", + "ita": "Italian", + "jav": "Javanese", + "jbo": "Lojban", + "jpn": "Japanese", + "jpr": "Judeo-Persian", + "jrb": "Judeo-Arabic", "kaa": "Kara-Kalpak", "kab": "Kabyle", - "kac": "Katsjin", - "kal": "Groenlands", + "kac": "Kachin", + "kal": "Kalaallisut", "kam": "Kamba (Kenya)", - "kan": "Kannada; Kanara; Kanarees", + "kan": "Kannada", "kas": "Kashmiri", - "kat": "Georgisch", + "kat": "Georgian", "kau": "Kanuri", "kaw": "Kawi", - "kaz": "Kazachs", - "kbd": "Kabardisch; Tsjerkessisch", + "kaz": "Kazakh", + "kbd": "Kabardian", "kha": "Khasi", - "khm": "Khmer, Cambodjaans", - "kho": "Khotanees", + "khm": "Khmer; Central", + "kho": "Khotanese", "kik": "Kikuyu", "kin": "Kinyarwanda", - "kir": "Kirgizisch", + "kir": "Kirghiz", "kmb": "Kimbundu", - "kok": "Konkani", + "kok": "Konkani (macrolanguage)", "kom": "Komi", - "kon": "Kikongo", - "kor": "Koreaans", - "kos": "Kosraeaans", + "kon": "Kongo", + "kor": "Korean", + "kos": "Kosraean", "kpe": "Kpelle", - "krc": "Karatsjay-Balkar", - "krl": "Karelisch", + "krc": "Karachay-Balkar", + "krl": "Karelian", "kru": "Kurukh", "kua": "Kuanyama", "kum": "Kumyk", - "kur": "Koerdisch", - "kut": "Kutenaïsch", + "kur": "Kurdish", + "kut": "Kutenai", "lad": "Ladino", "lah": "Lahnda", "lam": "Lamba", - "lao": "Laotiaans", - "lat": "Latijn", - "lav": "Lets", - "lez": "Lezghiaans", - "lim": "Limburgs", + "lao": "Lao", + "lat": "Latin", + "lav": "Latvian", + "lez": "Lezghian", + "lim": "Limburgan", "lin": "Lingala", - "lit": "Litouws", + "lit": "Lithuanian", "lol": "Mongo", "loz": "Lozi", - "ltz": "Luxemburgs", + "ltz": "Luxembourgish", "lua": "Luba-Lulua", "lub": "Luba-Katanga", - "lug": "Luganda", + "lug": "Ganda", "lui": "Luiseno", "lun": "Lunda", - "luo": "Luo (Kenia en Tanzania)", + "luo": "Luo (Kenya and Tanzania)", "lus": "Lushai", - "mad": "Madurees", - "mag": "Magahisch", - "mah": "Marshallees", + "mad": "Madurese", + "mag": "Magahi", + "mah": "Marshallese", "mai": "Maithili", "mak": "Makasar", "mal": "Malayalam", "man": "Mandingo", "mar": "Marathi", "mas": "Masai", - "mdf": "Moksja", - "mdr": "Mandars", - "men": "Mende", - "mga": "Iers; middel (900-1200)", - "mic": "Mi'kmaq; Micmac", + "mdf": "Moksha", + "mdr": "Mandar", + "men": "Mende (Sierra Leone)", + "mga": "Irish; Middle (900-1200)", + "mic": "Mi'kmaq", "min": "Minangkabau", - "mis": "Niet-gecodeerde talen", - "mkd": "Macedonisch", - "mlg": "Malagassisch", - "mlt": "Maltees", + "mis": "Uncoded languages", + "mkd": "Macedonian", + "mlg": "Malagasy", + "mlt": "Maltese", "mnc": "Manchu", "mni": "Manipuri", "moh": "Mohawk", - "mon": "Mongools", - "mos": "Mossisch", + "mon": "Mongolian", + "mos": "Mossi", "mri": "Maori", - "msa": "Maleis", - "mul": "Meerdere talen", + "msa": "Malay (macrolanguage)", + "mul": "Multiple languages", "mus": "Creek", - "mwl": "Mirandees", + "mwl": "Mirandese", "mwr": "Marwari", - "mya": "Burmees", + "mya": "Burmese", "myv": "Erzya", - "nap": "Napolitaans", - "nau": "Nauruaans", + "nap": "Neapolitan", + "nau": "Nauru", "nav": "Navajo", - "nbl": "Ndebele; zuid", - "nde": "Ndebele; noord", + "nbl": "Ndebele; South", + "nde": "Ndebele; North", "ndo": "Ndonga", - "nds": "Duits; Laag", - "nep": "Nepalees", - "new": "Newari; Nepal", + "nds": "German; Low", + "nep": "Nepali", + "new": "Bhasa; Nepal", "nia": "Nias", - "niu": "Niueaans", - "nld": "Nederlands", - "nno": "Noors; Nynorsk", - "nob": "Noors; Bokmål", + "niu": "Niuean", + "nld": "Dutch", + "nno": "Norwegian Nynorsk", + "nob": "Norwegian Bokmål", "nog": "Nogai", - "non": "Noors; oud", - "nor": "Noors", + "non": "Norse; Old", + "nor": "Norwegian", "nqo": "N'Ko", - "nso": "Pedi; Sepedi; Noord-Sothotisch", - "nwc": "Newari; Klassiek Nepal", + "nso": "Sotho; Northern", + "nwc": "Newari; Old", "nya": "Nyanja", "nym": "Nyamwezi", - "nyn": "Nyankools", + "nyn": "Nyankole", "nyo": "Nyoro", "nzi": "Nzima", - "oci": "Occitaans (na 1500)", + "oci": "Occitan (post 1500)", "oji": "Ojibwa", "ori": "Oriya", "orm": "Oromo", - "osa": "Osaags", - "oss": "Ossetisch", - "ota": "Turks; ottomaans (1500-1928)", - "pag": "Pangasinaans", - "pal": "Pehlevi", + "osa": "Osage", + "oss": "Ossetian", + "ota": "Turkish; Ottoman (1500-1928)", + "pag": "Pangasinan", + "pal": "Pahlavi", "pam": "Pampanga", - "pan": "Punjabi", + "pan": "Panjabi", "pap": "Papiamento", - "pau": "Palauaans", - "peo": "Perzisch; oud (ca. 600-400 B.C.)", - "phn": "Foenisisch", + "pau": "Palauan", + "peo": "Persian; Old (ca. 600-400 B.C.)", + "phn": "Phoenician", "pli": "Pali", - "pol": "Pools", - "pon": "Pohnpeiaans", - "por": "Portugees", - "pro": "Provençaals; oud (tot 1500)", - "pus": "Poesjto", + "pol": "Polish", + "pon": "Pohnpeian", + "por": "Portuguese", + "pro": "Provençal; Old (to 1500)", + "pus": "Pashto", "que": "Quechua", "raj": "Rajasthani", "rap": "Rapanui", - "rar": "Rarotongan; Cookeilanden Maori", - "roh": "Reto-Romaans", - "rom": "Romani", - "ron": "Roemeens", + "rar": "Maori; Cook Islands", + "roh": "Romansh", + "rom": "Romany", + "ron": "Romanian", "run": "Rundi", - "rup": "Roemeens; Macedo-", - "rus": "Russisch", + "rup": "Romanian; Macedo-", + "rus": "Russian", "sad": "Sandawe", - "sag": "Sangho", - "sah": "Jakoets", - "sam": "Aramees; Samaritaans", - "san": "Sanskriet", - "sas": "Sasaaks", + "sag": "Sango", + "sah": "Yakut", + "sam": "Aramaic; Samaritan", + "san": "Sanskrit", + "sas": "Sasak", "sat": "Santali", - "scn": "Siciliaans", - "sco": "Schots", - "sel": "Sulkoeps", - "sga": "Iers; oud (tot 900)", - "shn": "Sjaans", + "scn": "Sicilian", + "sco": "Scots", + "sel": "Selkup", + "sga": "Irish; Old (to 900)", + "shn": "Shan", "sid": "Sidamo", "sin": "Sinhala", - "slk": "Slowaaks", - "slv": "Sloveens", - "sma": "Samisch; zuid, Laps; zuid", - "sme": "Samisch; noord, Laps; noord", + "slk": "Slovak", + "slv": "Slovenian", + "sma": "Sami; Southern", + "sme": "Sami; Northern", "smj": "Lule Sami", - "smn": "Sami; Inari, Laps; Inari", - "smo": "Samoaans", - "sms": "Sami; Skolt, Laps; Skolt", + "smn": "Sami; Inari", + "smo": "Samoan", + "sms": "Sami; Skolt", "sna": "Shona", "snd": "Sindhi", "snk": "Soninke", - "sog": "Sogdiaans", - "som": "Somalisch", - "sot": "Sothaans; zuidelijk", - "spa": "Spaans", - "sqi": "Albanees", - "srd": "Sardinisch", + "sog": "Sogdian", + "som": "Somali", + "sot": "Sotho; Southern", + "spa": "Spanish", + "sqi": "Albanian", + "srd": "Sardinian", "srn": "Sranan Tongo", - "srp": "Servisch", + "srp": "Serbian", "srr": "Serer", "ssw": "Swati", "suk": "Sukuma", - "sun": "Soendanees; Sundanees", + "sun": "Sundanese", "sus": "Susu", - "sux": "Sumerisch", - "swa": "Swahili", - "swe": "Zweeds", - "syc": "Syriac; Klassiek", - "syr": "Syrisch", - "tah": "Tahitisch", + "sux": "Sumerian", + "swa": "Swahili (macrolanguage)", + "swe": "Swedish", + "syc": "Syriac; Classical", + "syr": "Syriac", + "tah": "Tahitian", "tam": "Tamil", - "tat": "Tataars", + "tat": "Tatar", "tel": "Telugu", "tem": "Timne", "ter": "Tereno", "tet": "Tetum", - "tgk": "Tadzjieks", + "tgk": "Tajik", "tgl": "Tagalog", "tha": "Thai", "tig": "Tigre", "tir": "Tigrinya", "tiv": "Tiv", "tkl": "Tokelau", - "tlh": "Klingon; tlhIngan-Hol", + "tlh": "Klingon", "tli": "Tlingit", - "tmh": "Tamasjek", + "tmh": "Tamashek", "tog": "Tonga (Nyasa)", - "ton": "Tonga (Tonga-eilanden)", + "ton": "Tonga (Tonga Islands)", "tpi": "Tok Pisin", - "tsi": "Tsimsjiaans", + "tsi": "Tsimshian", "tsn": "Tswana", "tso": "Tsonga", - "tuk": "Turkmeens", + "tuk": "Turkmen", "tum": "Tumbuka", - "tur": "Turks", + "tur": "Turkish", "tvl": "Tuvalu", "twi": "Twi", - "tyv": "Tuviniaans", - "udm": "Udmurts", - "uga": "Ugaritisch", - "uig": "Oeigoers; Oejgoers", - "ukr": "Oekraïens", + "tyv": "Tuvinian", + "udm": "Udmurt", + "uga": "Ugaritic", + "uig": "Uighur", + "ukr": "Ukrainian", "umb": "Umbundu", - "und": "Onbepaald", + "und": "Undetermined", "urd": "Urdu", - "uzb": "Oezbeeks", + "uzb": "Uzbek", "vai": "Vai", "ven": "Venda", - "vie": "Vietnamees", + "vie": "Vietnamese", "vol": "Volapük", - "vot": "Votisch", - "wal": "Walamo", - "war": "Waray (Filipijns)", - "was": "Wasjo", - "wln": "Waals", + "vot": "Votic", + "wal": "Wolaytta", + "war": "Waray (Philippines)", + "was": "Washo", + "wln": "Walloon", "wol": "Wolof", "xal": "Kalmyk", "xho": "Xhosa", "yao": "Yao", - "yap": "Yapees", - "yid": "Jiddisch", + "yap": "Yapese", + "yid": "Yiddish", "yor": "Yoruba", "zap": "Zapotec", - "zbl": "Blissymbolen", + "zbl": "Blissymbols", "zen": "Zenaga", - "zha": "Zhuang, Tsjoeang", - "zho": "Chinees", - "zul": "Zoeloe", + "zha": "Zhuang", + "zho": "Chinese", + "zul": "Zulu", "zun": "Zuni", - "zxx": "Geen linguïstische inhoud", + "zxx": "No linguistic content", "zza": "Zaza" }, - "pl": { - "aar": "afarski", - "abk": "abchaski", - "ace": "aczineski", - "ach": "aczoli", - "ada": "adangme", - "ady": "adygejski", - "afh": "afrihili", - "afr": "afrykanerski", - "ain": "ajnoski (Japonia)", - "aka": "akan", - "akk": "akadyjski", - "ale": "aleucki", - "alt": "ałtajski południowy", - "amh": "amharski", - "ang": "Staroangielski (ok. 450-1100)", - "anp": "angika", - "ara": "arabski", - "arc": "aramejski oficjalny (700-300 p.n.e.)", - "arg": "aragoński", - "arn": "araukański", - "arp": "arapaho", - "arw": "arawak", - "asm": "asamski", - "ast": "asturyjski", - "ava": "awarski", - "ave": "awestyjski", - "awa": "awadhi", - "aym": "ajmara", - "aze": "azerski", - "bak": "baszkirski", - "bal": "baluczi", - "bam": "bambara", - "ban": "balijski", - "bas": "basa (Kamerun)", - "bej": "bedża", - "bel": "białoruski", - "bem": "bemba (Zambia)", - "ben": "bengalski", - "bho": "bhodźpuri", - "bik": "bikol", - "bin": "edo", - "bis": "bislama", + "ko": { + "abk": "압하스어", + "ace": "아체어", + "ach": "아촐리어", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "아파르어", + "afh": "Afrihili", + "afr": "아프리칸스어", + "ain": "Ainu (Japan)", + "aka": "Akan", + "akk": "Akkadian", + "sqi": "Albanian", + "ale": "Aleut", + "amh": "Amharic", + "anp": "Angika", + "ara": "아라비아어", + "arg": "Aragonese", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "아르메니아어", + "asm": "Assamese", + "ast": "Asturian", + "ava": "Avaric", + "ave": "아베스타어", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Azerbaijani", + "ban": "발리 문자", + "bal": "Baluchi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Bashkir", + "eus": "바스크어", + "bej": "Beja", + "bel": "벨로루시어", + "bem": "Bemba (Zambia)", + "ben": "벵골 문자", "bit": "Berinomo", - "bla": "siksika", - "bod": "tybetański", - "bos": "bośniacki", - "bra": "bradź", - "bre": "bretoński", - "bua": "buriacki", - "bug": "bugijski", - "bul": "bułgarski", - "byn": "blin", - "cad": "kaddo", - "car": "karaibski galibi", - "cat": "kataloński", - "ceb": "cebuański", - "ces": "czeski", - "cha": "czamorro", - "chb": "czibcza", - "che": "czeczeński", - "chg": "czagatajski", - "chk": "chuuk", - "chm": "maryjski (Rosja)", - "chn": "żargon chinoocki", - "cho": "czoktaw", - "chp": "chipewyan", - "chr": "czerokeski", + "bho": "Bhojpuri", + "bik": "Bikol", + "byn": "Bilin", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Blissymbols", + "bos": "Bosnian", + "bra": "Braj", + "bre": "Breton", + "bug": "부기 문자", + "bul": "불가리아어", + "bua": "Buriat", + "mya": "Burmese", + "cad": "Caddo", + "cat": "카탈로니아어", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "Chamorro", + "che": "Chechen", + "chr": "체로키 문자", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "중국어", + "chn": "Chinook jargon", + "chp": "Chipewyan", + "cho": "Choctaw", "cht": "Cholón", - "chu": "starosłowiański", - "chv": "czuwaski", - "chy": "czejeński", - "cop": "koptyjski", - "cor": "kornijski", - "cos": "korsykański", - "cre": "kri", - "crh": "krymskotatarski", - "csb": "kaszubski", - "cym": "walijski", - "dak": "dakota", - "dan": "duński", - "dar": "dargwijski", - "del": "delaware", - "den": "slavey (atapaskański)", - "deu": "niemiecki", - "dgr": "dogrib", - "din": "dinka", - "div": "malediwski; divehi", - "doi": "dogri (makrojęzyk)", - "dsb": "dolnołużycki", - "dse": "holenderski język migowy", - "dua": "duala", - "dum": "holenderski średniowieczny (ok. 1050-1350)", - "dyu": "diula", - "dzo": "dzongka", - "efi": "efik", - "egy": "egipski (starożytny)", - "eka": "ekajuk", - "ell": "grecki współczesny (1453-)", - "elx": "elamicki", - "eng": "Angielski", - "enm": "angielski średniowieczny (1100-1500)", + "chk": "Chuukese", + "chv": "Chuvash", + "cop": "콥트어", + "cor": "Cornish", + "cos": "Corsican", + "cre": "Cree", + "mus": "Creek", + "hrv": "크로아티아어", + "ces": "체크어", + "dak": "Dakota", + "dan": "덴마크어", + "dar": "Dargwa", + "del": "Delaware", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "네덜란드어", + "dse": "Dutch Sign Language", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Egyptian (Ancient)", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "영어", "enu": "Enu", - "epo": "esperanto", - "est": "estoński", - "eus": "baskijski", - "ewe": "ewe", - "ewo": "ewondo", - "fan": "fang (Gwinea Równikowa)", - "fao": "farerski", - "fas": "perski", - "fat": "fanti", - "fij": "fidżyjski", - "fil": "pilipino", - "fin": "fiński", - "fon": "fon", - "fra": "francuski", - "frm": "francuski średniowieczny (ok. 1400-1600)", - "fro": "starofrancuski (842-ok. 1400)", - "frr": "północnofryzyjski", - "frs": "wschodniofryzyjski", - "fry": "zachodniofryzyjski", - "ful": "fulani", - "fur": "friulski", - "gaa": "ga", - "gay": "gayo", - "gba": "gbaya (Republika Środkowoafrykańska)", - "gez": "gyyz", - "gil": "gilbertański", - "gla": "szkocki gaelicki", - "gle": "irlandzki", - "glg": "galicyjski", - "glv": "manx", - "gmh": "średnio-wysoko-niemiecki (ok. 1050-1500)", - "goh": "staro-wysoko-niemiecki (ok. 750-1050)", - "gon": "gondi", - "gor": "gorontalo", - "got": "gocki", - "grb": "grebo", - "grc": "grecki starożytny (do 1453)", - "grn": "guarani", - "gsw": "niemiecki szwajcarski", - "guj": "gudźarati", - "gwi": "gwichʼin", - "hai": "haida", - "hat": "kreolski haitański", - "hau": "hausa", - "haw": "hawajski", - "heb": "hebrajski", - "her": "herero", - "hil": "hiligajnon", - "hin": "hindi", - "hit": "hetycki", + "myv": "Erzya", + "epo": "에스페란토어", + "est": "에스토니아어", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang (Equatorial Guinea)", + "fat": "Fanti", + "fao": "페로스어", + "fij": "Fijian", + "fil": "Filipino", + "fin": "핀란드어", + "fon": "Fon", + "fra": "프랑스어", + "fur": "Friulian", + "ful": "Fulah", + "gaa": "Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", "hmj": "Ge", - "hmn": "hmong", - "hmo": "hiri motu", - "hrv": "chorwacki", - "hsb": "górnołużycki", - "hun": "węgierski", - "hup": "hupa", - "hye": "ormiański", - "iba": "ibanag", - "ibo": "ibo", - "ido": "ido", - "iii": "syczuański", - "iku": "inuktitut", - "ile": "interlingue", - "ilo": "ilokano", - "ina": "interlingua (Międzynarodowe Stowarzyszenie Języka Pomocniczego)", - "ind": "indonezyjski", - "inh": "inguski", - "ipk": "inupiaq", - "isl": "islandzki", - "ita": "włoski", - "jav": "jawajski", - "jbo": "lojban", - "jpn": "japoński", - "jpr": "judeo-perski", - "jrb": "judeoarabski", - "kaa": "karakałpacki", - "kab": "kabylski", - "kac": "kaczin", - "kal": "kalaallisut", - "kam": "kamba (Kenia)", - "kan": "kannada", - "kas": "kaszmirski", - "kat": "gruziński", - "kau": "kanuri", - "kaw": "kawi", - "kaz": "kazaski", - "kbd": "kabardyjski", - "kha": "khasi", - "khm": "środkowokhmerski", - "kho": "chotański", - "kik": "kikiju", - "kin": "ruanda", - "kir": "kirgiski", - "kmb": "kimbundu", - "kok": "konkani (makrojęzyk)", - "kom": "komi", - "kon": "kongo", - "kor": "koreański", - "kos": "kosrae", - "kpe": "kpelle", - "krc": "karaczajsko-bałkarski", - "krl": "karelski", - "kru": "kurukh", - "kua": "kwanyama", - "kum": "kumycki", - "kur": "kurdyjski", - "kut": "kutenai", - "lad": "ladino", - "lah": "lahnda", - "lam": "lamba", - "lao": "laotański", - "lat": "łaciński", - "lav": "łotewski", - "lez": "lezgiński", - "lim": "limburgijski", - "lin": "lingala", - "lit": "litewski", - "lol": "mongo", - "loz": "lozi", - "ltz": "luksemburski", - "lua": "luba-lulua", - "lub": "luba-katanga", - "lug": "luganda", - "lui": "luiseno", - "lun": "lunda", - "luo": "luo (Kenia i Tanzania)", - "lus": "lushai", - "mad": "madurajski", - "mag": "magahi", - "mah": "marshalski", - "mai": "maithili", - "mak": "makasar", - "mal": "malajalam", - "man": "mandingo", - "mar": "marathi", - "mas": "masajski", - "mdf": "moksza", - "mdr": "mandar", - "men": "mende (Sierra Leone)", + "gez": "Geez", + "kat": "그루지야어", + "deu": "독일어", + "gil": "Gilbertese", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "고트어", + "grb": "Grebo", + "grn": "Guarani", + "guj": "구자라트 문자", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Hausa", + "haw": "Hawaiian", + "heb": "헤브루어", + "her": "Herero", + "hil": "Hiligaynon", + "hin": "Hindi", + "hmo": "Hiri Motu", + "hit": "Hittite", + "hmn": "Hmong", + "hun": "헝가리어", + "hup": "Hupa", + "iba": "Iban", + "isl": "아이슬란드어", + "ido": "Ido", + "ibo": "Igbo", + "ilo": "Iloko", + "ind": "인도네시아어", + "inh": "Ingush", + "ina": "Interlingua (International Auxiliary Language Association)", + "ile": "Interlingue", + "iku": "Inuktitut", + "ipk": "Inupiaq", + "gle": "아일랜드어", + "ita": "이탈리아어", + "jpn": "일본어", + "jav": "Javanese", + "jrb": "Judeo-Arabic", + "jpr": "Judeo-Persian", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", + "kal": "Kalaallisut", + "xal": "Kalmyk", + "kam": "Kamba (Kenya)", + "kan": " 칸나다 문자", + "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": "한국어", + "kos": "Kosraean", + "kpe": "Kpelle", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Kurdish", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "라오 문자", + "lat": "Latin", + "lav": "라트비아어", + "lez": "Lezghian", + "lim": "Limburgan", + "lin": "Lingala", + "lit": "리투아니아어", + "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": "마케도니아어", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "Malagasy", + "msa": "Malay (macrolanguage)", + "mal": "말라얄람 문자", + "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": "몽골 문자", + "mos": "Mossi", + "mul": "Multiple languages", + "nqo": "응코 문자", + "nau": "나우루어", + "nav": "나바호어", + "ndo": "Ndonga", + "nap": "Neapolitan", + "nia": "Nias", + "niu": "Niuean", + "zxx": "No linguistic content", + "nog": "Nogai", + "nor": "노르웨이어", + "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": " 페니키아 문자", + "pon": "Pohnpeian", + "pol": "폴란드어", + "por": "포르투갈어", + "pus": "Pashto", + "que": "Quechua", + "raj": "Rajasthani", + "rap": "Rapanui", + "ron": "루마니아어", + "roh": "Romansh", + "rom": "Romany", + "run": "Rundi", + "rus": "러시아어", + "smo": "Samoan", + "sad": "Sandawe", + "sag": "Sango", + "san": "Sanskrit", + "sat": "Santali", + "srd": "Sardinian", + "sas": "Sasak", + "sco": "Scots", + "sel": "Selkup", + "srp": "세르비아어", + "srr": "Serer", + "shn": "Shan", + "sna": "Shona", + "scn": "Sicilian", + "sid": "Sidamo", + "bla": "Siksika", + "snd": "Sindhi", + "sin": "싱할라 문자", + "den": "Slave (Athapascan)", + "slk": "슬로바키아어", + "slv": "슬로베니아어", + "sog": "Sogdian", + "som": "Somali", + "snk": "Soninke", + "spa": "스페인어", + "srn": "Sranan Tongo", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sundanese", + "sus": "Susu", + "swa": "Swahili (macrolanguage)", + "ssw": "Swati", + "swe": "스웨덴어", + "syr": "시리아 문자", + "tgl": "타갈로그 문자", + "tah": "Tahitian", + "tgk": "Tajik", + "tmh": "Tamashek", + "tam": "타밀 문자", + "tat": "Tatar", + "tel": "텔루구 문자", + "ter": "Tereno", + "tet": "Tetum", + "tha": "태국어", + "bod": "티베트 문자", + "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": "터키어", + "tuk": "Turkmen", + "tvl": "Tuvalu", + "tyv": "Tuvinian", + "twi": "Twi", + "udm": "Udmurt", + "uga": "우가리트 문자", + "uig": "Uighur", + "ukr": "Ukrainian", + "umb": "Umbundu", + "mis": "Uncoded languages", + "und": "Undetermined", + "urd": "Urdu", + "uzb": "Uzbek", + "vai": "Vai", + "ven": "Venda", + "vie": "베트남어", + "vol": "Volapük", + "vot": "Votic", + "wln": "Walloon", + "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" + }, + "nl": { + "aar": "Afar; Hamitisch", + "abk": "Abchazisch", + "ace": "Achinees", + "ach": "Acholi", + "ada": "Adangme", + "ady": "Adyghe", + "afh": "Afrihili", + "afr": "Afrikaans", + "ain": "Ainu (Japan)", + "aka": "Akaans", + "akk": "Akkadiaans", + "ale": "Aleut", + "alt": "Altajs; zuidelijk", + "amh": "Amhaars; Amharisch", + "ang": "Engels; oud (ca. 450-1100)", + "anp": "Angika", + "ara": "Arabisch", + "arc": "Aramees; officieel (700-300 B.C.)", + "arg": "Aragonees", + "arn": "Mapudungun", + "arp": "Arapaho", + "arw": "Arawak", + "asm": "Assamees; Assami", + "ast": "Asturisch", + "ava": "Avaars; Awari", + "ave": "Avestisch", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Azerbeidzjaans", + "bak": "Basjkiers; Basjkirisch", + "bal": "Balutsji; Baluchi", + "bam": "Bambara", + "ban": "Balinees", + "bas": "Basa (Kameroen)", + "bej": "Beja", + "bel": "Wit-Russisch; Belarussisch", + "bem": "Bemba (Zambia)", + "ben": "Bengaals", + "bho": "Bhojpuri", + "bik": "Bikol", + "bin": "Bini; Edo", + "bis": "Bislama", + "bit": "Berinomo", + "bla": "Siksika", + "bod": "Tibetaans", + "bos": "Bosnisch", + "bra": "Braj", + "bre": "Bretons; Bretoens", + "bua": "Boeriaats", + "bug": "Buginees", + "bul": "Bulgaars", + "byn": "Bilin", + "cad": "Caddo", + "car": "Caribische talen", + "cat": "Catalaans", + "ceb": "Cebuano", + "ces": "Tsjechisch", + "cha": "Chamorro", + "chb": "Tsjibtsja", + "che": "Tsjetsjeens", + "chg": "Chagatai", + "chk": "Chukees", + "chm": "Mari (Rusland)", + "chn": "Chinook-jargon", + "cho": "Choctaw", + "chp": "Chipewyaans", + "chr": "Cherokee", + "cht": "Cholón", + "chu": "Slavisch; oud (kerk)", + "chv": "Tsjoevasjisch", + "chy": "Cheyenne", + "cop": "Koptisch", + "cor": "Cornisch", + "cos": "Corsicaans", + "cre": "Cree", + "crh": "Turks; Crimean", + "csb": "Kasjoebiaans", + "cym": "Welsh", + "dak": "Dakota", + "dan": "Deens", + "dar": "Dargwa", + "del": "Delaware", + "den": "Slavisch (Athapascaans)", + "deu": "Duits", + "dgr": "Dogrib", + "din": "Dinka", + "div": "Divehi", + "doi": "Dogri", + "dsb": "Sorbisch; lager", + "dse": "Nederlandse gebarentaal", + "dua": "Duala", + "dum": "Nederlands; middel (ca. 1050-1350)", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efikisch", + "egy": "Egyptisch (antiek)", + "eka": "Ekajuk", + "ell": "Grieks; Modern (1453-)", + "elx": "Elamitisch", + "eng": "Engels", + "enm": "Engels; middel (1100-1500)", + "enu": "Enu", + "epo": "Esperanto", + "est": "Estlands", + "eus": "Baskisch", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang", + "fao": "Faeröers", + "fas": "Perzisch", + "fat": "Fanti", + "fij": "Fijisch", + "fil": "Filipijns", + "fin": "Fins", + "fon": "Fon", + "fra": "Frans", + "frm": "Frans; middel (ca. 1400-1600)", + "fro": "Frans; oud (842-ca. 1400)", + "frr": "Fries; noordelijk (Duitsland)", + "frs": "Fries; oostelijk (Duitsland)", + "fry": "Fries", + "ful": "Fulah", + "fur": "Friulisch", + "gaa": "Ga", + "gay": "Gayo", + "gba": "Gbaya (Centraal Afrikaanse Republiek)", + "gez": "Ge'ez", + "gil": "Gilbertees", + "gla": "Keltisch; schots", + "gle": "Iers", + "glg": "Galiciaans", + "glv": "Manx", + "gmh": "Duits; middel hoog (ca. 1050-1500)", + "goh": "Duits; oud hoog (ca. 750-1050)", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gothisch", + "grb": "Grebo", + "grc": "Grieks; antiek (tot 1453)", + "grn": "Guarani", + "gsw": "Duits; Zwitserland", + "guj": "Gujarati", + "gwi": "Gwichʼin", + "hai": "Haida", + "hat": "Creools; Haïtiaans", + "hau": "Hausa", + "haw": "Hawaiiaans", + "heb": "Hebreeuws", + "her": "Herero", + "hil": "Hiligainoons", + "hin": "Hindi", + "hit": "Hittitisch", + "hmj": "Ge", + "hmn": "Hmong", + "hmo": "Hiri Motu", + "hrv": "Kroatisch", + "hsb": "Servisch; hoger", + "hun": "Hongaars", + "hup": "Hupa", + "hye": "Armeens", + "iba": "Ibaans", + "ibo": "Igbo", + "ido": "Ido", + "iii": "Yi; Sichuan - Nuosu", + "iku": "Inuktitut", + "ile": "Interlingue", + "ilo": "Iloko", + "ina": "Interlingua (International Auxiliary Language Association)", + "ind": "Indonesisch", + "inh": "Ingoesjetisch", + "ipk": "Inupiak", + "isl": "IJslands", + "ita": "Italiaans", + "jav": "Javaans", + "jbo": "Lojbaans", + "jpn": "Japans", + "jpr": "Joods-Perzisch", + "jrb": "Joods-Arabisch", + "kaa": "Kara-Kalpak", + "kab": "Kabyle", + "kac": "Katsjin", + "kal": "Groenlands", + "kam": "Kamba (Kenya)", + "kan": "Kannada; Kanara; Kanarees", + "kas": "Kashmiri", + "kat": "Georgisch", + "kau": "Kanuri", + "kaw": "Kawi", + "kaz": "Kazachs", + "kbd": "Kabardisch; Tsjerkessisch", + "kha": "Khasi", + "khm": "Khmer, Cambodjaans", + "kho": "Khotanees", + "kik": "Kikuyu", + "kin": "Kinyarwanda", + "kir": "Kirgizisch", + "kmb": "Kimbundu", + "kok": "Konkani", + "kom": "Komi", + "kon": "Kikongo", + "kor": "Koreaans", + "kos": "Kosraeaans", + "kpe": "Kpelle", + "krc": "Karatsjay-Balkar", + "krl": "Karelisch", + "kru": "Kurukh", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Koerdisch", + "kut": "Kutenaïsch", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "Laotiaans", + "lat": "Latijn", + "lav": "Lets", + "lez": "Lezghiaans", + "lim": "Limburgs", + "lin": "Lingala", + "lit": "Litouws", + "lol": "Mongo", + "loz": "Lozi", + "ltz": "Luxemburgs", + "lua": "Luba-Lulua", + "lub": "Luba-Katanga", + "lug": "Luganda", + "lui": "Luiseno", + "lun": "Lunda", + "luo": "Luo (Kenia en Tanzania)", + "lus": "Lushai", + "mad": "Madurees", + "mag": "Magahisch", + "mah": "Marshallees", + "mai": "Maithili", + "mak": "Makasar", + "mal": "Malayalam", + "man": "Mandingo", + "mar": "Marathi", + "mas": "Masai", + "mdf": "Moksja", + "mdr": "Mandars", + "men": "Mende", + "mga": "Iers; middel (900-1200)", + "mic": "Mi'kmaq; Micmac", + "min": "Minangkabau", + "mis": "Niet-gecodeerde talen", + "mkd": "Macedonisch", + "mlg": "Malagassisch", + "mlt": "Maltees", + "mnc": "Manchu", + "mni": "Manipuri", + "moh": "Mohawk", + "mon": "Mongools", + "mos": "Mossisch", + "mri": "Maori", + "msa": "Maleis", + "mul": "Meerdere talen", + "mus": "Creek", + "mwl": "Mirandees", + "mwr": "Marwari", + "mya": "Burmees", + "myv": "Erzya", + "nap": "Napolitaans", + "nau": "Nauruaans", + "nav": "Navajo", + "nbl": "Ndebele; zuid", + "nde": "Ndebele; noord", + "ndo": "Ndonga", + "nds": "Duits; Laag", + "nep": "Nepalees", + "new": "Newari; Nepal", + "nia": "Nias", + "niu": "Niueaans", + "nld": "Nederlands", + "nno": "Noors; Nynorsk", + "nob": "Noors; Bokmål", + "nog": "Nogai", + "non": "Noors; oud", + "nor": "Noors", + "nqo": "N'Ko", + "nso": "Pedi; Sepedi; Noord-Sothotisch", + "nwc": "Newari; Klassiek Nepal", + "nya": "Nyanja", + "nym": "Nyamwezi", + "nyn": "Nyankools", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitaans (na 1500)", + "oji": "Ojibwa", + "ori": "Oriya", + "orm": "Oromo", + "osa": "Osaags", + "oss": "Ossetisch", + "ota": "Turks; ottomaans (1500-1928)", + "pag": "Pangasinaans", + "pal": "Pehlevi", + "pam": "Pampanga", + "pan": "Punjabi", + "pap": "Papiamento", + "pau": "Palauaans", + "peo": "Perzisch; oud (ca. 600-400 B.C.)", + "phn": "Foenisisch", + "pli": "Pali", + "pol": "Pools", + "pon": "Pohnpeiaans", + "por": "Portugees", + "pro": "Provençaals; oud (tot 1500)", + "pus": "Poesjto", + "que": "Quechua", + "raj": "Rajasthani", + "rap": "Rapanui", + "rar": "Rarotongan; Cookeilanden Maori", + "roh": "Reto-Romaans", + "rom": "Romani", + "ron": "Roemeens", + "run": "Rundi", + "rup": "Roemeens; Macedo-", + "rus": "Russisch", + "sad": "Sandawe", + "sag": "Sangho", + "sah": "Jakoets", + "sam": "Aramees; Samaritaans", + "san": "Sanskriet", + "sas": "Sasaaks", + "sat": "Santali", + "scn": "Siciliaans", + "sco": "Schots", + "sel": "Sulkoeps", + "sga": "Iers; oud (tot 900)", + "shn": "Sjaans", + "sid": "Sidamo", + "sin": "Sinhala", + "slk": "Slowaaks", + "slv": "Sloveens", + "sma": "Samisch; zuid, Laps; zuid", + "sme": "Samisch; noord, Laps; noord", + "smj": "Lule Sami", + "smn": "Sami; Inari, Laps; Inari", + "smo": "Samoaans", + "sms": "Sami; Skolt, Laps; Skolt", + "sna": "Shona", + "snd": "Sindhi", + "snk": "Soninke", + "sog": "Sogdiaans", + "som": "Somalisch", + "sot": "Sothaans; zuidelijk", + "spa": "Spaans", + "sqi": "Albanees", + "srd": "Sardinisch", + "srn": "Sranan Tongo", + "srp": "Servisch", + "srr": "Serer", + "ssw": "Swati", + "suk": "Sukuma", + "sun": "Soendanees; Sundanees", + "sus": "Susu", + "sux": "Sumerisch", + "swa": "Swahili", + "swe": "Zweeds", + "syc": "Syriac; Klassiek", + "syr": "Syrisch", + "tah": "Tahitisch", + "tam": "Tamil", + "tat": "Tataars", + "tel": "Telugu", + "tem": "Timne", + "ter": "Tereno", + "tet": "Tetum", + "tgk": "Tadzjieks", + "tgl": "Tagalog", + "tha": "Thai", + "tig": "Tigre", + "tir": "Tigrinya", + "tiv": "Tiv", + "tkl": "Tokelau", + "tlh": "Klingon; tlhIngan-Hol", + "tli": "Tlingit", + "tmh": "Tamasjek", + "tog": "Tonga (Nyasa)", + "ton": "Tonga (Tonga-eilanden)", + "tpi": "Tok Pisin", + "tsi": "Tsimsjiaans", + "tsn": "Tswana", + "tso": "Tsonga", + "tuk": "Turkmeens", + "tum": "Tumbuka", + "tur": "Turks", + "tvl": "Tuvalu", + "twi": "Twi", + "tyv": "Tuviniaans", + "udm": "Udmurts", + "uga": "Ugaritisch", + "uig": "Oeigoers; Oejgoers", + "ukr": "Oekraïens", + "umb": "Umbundu", + "und": "Onbepaald", + "urd": "Urdu", + "uzb": "Oezbeeks", + "vai": "Vai", + "ven": "Venda", + "vie": "Vietnamees", + "vol": "Volapük", + "vot": "Votisch", + "wal": "Walamo", + "war": "Waray (Filipijns)", + "was": "Wasjo", + "wln": "Waals", + "wol": "Wolof", + "xal": "Kalmyk", + "xho": "Xhosa", + "yao": "Yao", + "yap": "Yapees", + "yid": "Jiddisch", + "yor": "Yoruba", + "zap": "Zapotec", + "zbl": "Blissymbolen", + "zen": "Zenaga", + "zha": "Zhuang, Tsjoeang", + "zho": "Chinees", + "zul": "Zoeloe", + "zun": "Zuni", + "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", + "ace": "aczineski", + "ach": "aczoli", + "ada": "adangme", + "ady": "adygejski", + "afh": "afrihili", + "afr": "afrykanerski", + "ain": "ajnoski (Japonia)", + "aka": "akan", + "akk": "akadyjski", + "ale": "aleucki", + "alt": "ałtajski południowy", + "amh": "amharski", + "ang": "Staroangielski (ok. 450-1100)", + "anp": "angika", + "ara": "arabski", + "arc": "aramejski oficjalny (700-300 p.n.e.)", + "arg": "aragoński", + "arn": "araukański", + "arp": "arapaho", + "arw": "arawak", + "asm": "asamski", + "ast": "asturyjski", + "ava": "awarski", + "ave": "awestyjski", + "awa": "awadhi", + "aym": "ajmara", + "aze": "azerski", + "bak": "baszkirski", + "bal": "baluczi", + "bam": "bambara", + "ban": "balijski", + "bas": "basa (Kamerun)", + "bej": "bedża", + "bel": "białoruski", + "bem": "bemba (Zambia)", + "ben": "bengalski", + "bho": "bhodźpuri", + "bik": "bikol", + "bin": "edo", + "bis": "bislama", + "bit": "Berinomo", + "bla": "siksika", + "bod": "tybetański", + "bos": "bośniacki", + "bra": "bradź", + "bre": "bretoński", + "bua": "buriacki", + "bug": "bugijski", + "bul": "bułgarski", + "byn": "blin", + "cad": "kaddo", + "car": "karaibski galibi", + "cat": "kataloński", + "ceb": "cebuański", + "ces": "czeski", + "cha": "czamorro", + "chb": "czibcza", + "che": "czeczeński", + "chg": "czagatajski", + "chk": "chuuk", + "chm": "maryjski (Rosja)", + "chn": "żargon chinoocki", + "cho": "czoktaw", + "chp": "chipewyan", + "chr": "czerokeski", + "cht": "Cholón", + "chu": "starosłowiański", + "chv": "czuwaski", + "chy": "czejeński", + "cop": "koptyjski", + "cor": "kornijski", + "cos": "korsykański", + "cre": "kri", + "crh": "krymskotatarski", + "csb": "kaszubski", + "cym": "walijski", + "dak": "dakota", + "dan": "duński", + "dar": "dargwijski", + "del": "delaware", + "den": "slavey (atapaskański)", + "deu": "niemiecki", + "dgr": "dogrib", + "din": "dinka", + "div": "malediwski; divehi", + "doi": "dogri (makrojęzyk)", + "dsb": "dolnołużycki", + "dse": "holenderski język migowy", + "dua": "duala", + "dum": "holenderski średniowieczny (ok. 1050-1350)", + "dyu": "diula", + "dzo": "dzongka", + "efi": "efik", + "egy": "egipski (starożytny)", + "eka": "ekajuk", + "ell": "grecki współczesny (1453-)", + "elx": "elamicki", + "eng": "Angielski", + "enm": "angielski średniowieczny (1100-1500)", + "enu": "Enu", + "epo": "esperanto", + "est": "estoński", + "eus": "baskijski", + "ewe": "ewe", + "ewo": "ewondo", + "fan": "fang (Gwinea Równikowa)", + "fao": "farerski", + "fas": "perski", + "fat": "fanti", + "fij": "fidżyjski", + "fil": "pilipino", + "fin": "fiński", + "fon": "fon", + "fra": "francuski", + "frm": "francuski średniowieczny (ok. 1400-1600)", + "fro": "starofrancuski (842-ok. 1400)", + "frr": "północnofryzyjski", + "frs": "wschodniofryzyjski", + "fry": "zachodniofryzyjski", + "ful": "fulani", + "fur": "friulski", + "gaa": "ga", + "gay": "gayo", + "gba": "gbaya (Republika Środkowoafrykańska)", + "gez": "gyyz", + "gil": "gilbertański", + "gla": "szkocki gaelicki", + "gle": "irlandzki", + "glg": "galicyjski", + "glv": "manx", + "gmh": "średnio-wysoko-niemiecki (ok. 1050-1500)", + "goh": "staro-wysoko-niemiecki (ok. 750-1050)", + "gon": "gondi", + "gor": "gorontalo", + "got": "gocki", + "grb": "grebo", + "grc": "grecki starożytny (do 1453)", + "grn": "guarani", + "gsw": "niemiecki szwajcarski", + "guj": "gudźarati", + "gwi": "gwichʼin", + "hai": "haida", + "hat": "kreolski haitański", + "hau": "hausa", + "haw": "hawajski", + "heb": "hebrajski", + "her": "herero", + "hil": "hiligajnon", + "hin": "hindi", + "hit": "hetycki", + "hmj": "Ge", + "hmn": "hmong", + "hmo": "hiri motu", + "hrv": "chorwacki", + "hsb": "górnołużycki", + "hun": "węgierski", + "hup": "hupa", + "hye": "ormiański", + "iba": "ibanag", + "ibo": "ibo", + "ido": "ido", + "iii": "syczuański", + "iku": "inuktitut", + "ile": "interlingue", + "ilo": "ilokano", + "ina": "interlingua (Międzynarodowe Stowarzyszenie Języka Pomocniczego)", + "ind": "indonezyjski", + "inh": "inguski", + "ipk": "inupiaq", + "isl": "islandzki", + "ita": "włoski", + "jav": "jawajski", + "jbo": "lojban", + "jpn": "japoński", + "jpr": "judeo-perski", + "jrb": "judeoarabski", + "kaa": "karakałpacki", + "kab": "kabylski", + "kac": "kaczin", + "kal": "kalaallisut", + "kam": "kamba (Kenia)", + "kan": "kannada", + "kas": "kaszmirski", + "kat": "gruziński", + "kau": "kanuri", + "kaw": "kawi", + "kaz": "kazaski", + "kbd": "kabardyjski", + "kha": "khasi", + "khm": "środkowokhmerski", + "kho": "chotański", + "kik": "kikiju", + "kin": "ruanda", + "kir": "kirgiski", + "kmb": "kimbundu", + "kok": "konkani (makrojęzyk)", + "kom": "komi", + "kon": "kongo", + "kor": "koreański", + "kos": "kosrae", + "kpe": "kpelle", + "krc": "karaczajsko-bałkarski", + "krl": "karelski", + "kru": "kurukh", + "kua": "kwanyama", + "kum": "kumycki", + "kur": "kurdyjski", + "kut": "kutenai", + "lad": "ladino", + "lah": "lahnda", + "lam": "lamba", + "lao": "laotański", + "lat": "łaciński", + "lav": "łotewski", + "lez": "lezgiński", + "lim": "limburgijski", + "lin": "lingala", + "lit": "litewski", + "lol": "mongo", + "loz": "lozi", + "ltz": "luksemburski", + "lua": "luba-lulua", + "lub": "luba-katanga", + "lug": "luganda", + "lui": "luiseno", + "lun": "lunda", + "luo": "luo (Kenia i Tanzania)", + "lus": "lushai", + "mad": "madurajski", + "mag": "magahi", + "mah": "marshalski", + "mai": "maithili", + "mak": "makasar", + "mal": "malajalam", + "man": "mandingo", + "mar": "marathi", + "mas": "masajski", + "mdf": "moksza", + "mdr": "mandar", + "men": "mende (Sierra Leone)", "mga": "irlandzki średniowieczny (900-1200)", "mic": "micmac", "min": "minangkabau", @@ -5445,808 +6579,1564 @@ LANGUAGE_NAMES = { "zxx": "brak kontekstu językowego", "zza": "zazaki" }, - "pt_BR": { - "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", + "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", + "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" + }, + "ru": { + "aar": "Афар", + "abk": "Абхазский", + "ace": "Ачехский", + "ach": "Ачоли", + "ada": "Адангме", + "ady": "Адыгейский", + "afh": "Африхили", + "afr": "Африкаанс", + "ain": "Ainu (Japan)", + "aka": "Акан", + "akk": "Аккадский", + "ale": "Алеутский", + "alt": "Altai; Southern", + "amh": "Амхарский (Амаринья)", + "ang": "English; Old (ca. 450-1100)", + "anp": "Анжика", + "ara": "Арабский", + "arc": "Арамейский; Официальный", + "arg": "Арагонский", + "arn": "Mapudungun", + "arp": "Арапахо", + "arw": "Аравакский", + "asm": "Ассамский", + "ast": "Астурийский", + "ava": "Аварский", + "ave": "Авестийский", + "awa": "Авадхи", + "aym": "Аймара", + "aze": "Азербайджанский", + "bak": "Башкирский", + "bal": "Baluchi", + "bam": "Бамбара", + "ban": "Балийский", + "bas": "Баса (Камерун)", + "bej": "Беджа", + "bel": "Белорусский", + "bem": "Бемба (Замбия)", + "ben": "Бенгальский", + "bho": "Бходжпури", + "bik": "Бикольский", + "bin": "Бини", + "bis": "Бислама", "bit": "Berinomo", - "bho": "Bhojpuri", - "bik": "Bikol", + "bla": "Сиксика", + "bod": "Тибетский", + "bos": "Боснийский", + "bra": "Браун", + "bre": "Бретонский", + "bua": "Бурятский", + "bug": "Бугийский", + "bul": "Болгарский", "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", + "cad": "Каддо", + "car": "Carib; Galibi", + "cat": "Каталанский", + "ceb": "Себуано", + "ces": "Чешский", + "cha": "Чаморро", + "chb": "Чибча", + "che": "Чеченский", + "chg": "Чагатайский", + "chk": "Трукский", + "chm": "Марийский (Россия)", + "chn": "Чинук жаргон", + "cho": "Чоктав", + "chp": "Чипевианский", + "chr": "Чероки", "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", + "chu": "Slavonic; Old", + "chv": "Чувашский", + "chy": "Чейенн", + "cop": "Коптский", + "cor": "Корнский", + "cos": "Корсиканский", + "cre": "Кри", + "crh": "Turkish; Crimean", + "csb": "Кашубианский", + "cym": "Уэльский (Валлийский)", + "dak": "Дакота", + "dan": "Датский", + "dar": "Даргва", + "del": "Делаварский", + "den": "Атапачские языки", + "deu": "Немецкий", + "dgr": "Догриб", + "din": "Динка", "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", + "dsb": "Sorbian; Lower", + "dse": "Dutch Sign Language", + "dua": "Дуала", + "dum": "Dutch; Middle (ca. 1050-1350)", + "dyu": "Диула (Дьюла)", + "dzo": "Дзонг-кэ", + "efi": "Эфик", + "egy": "Древнеегипетский", + "eka": "Экаджук", + "ell": "Новогреческий (с 1453)", + "elx": "Эламский", + "eng": "Английский", + "enm": "Среднеанглийский (1100-1500)", "enu": "Enu", - "myv": "Erzya", - "epo": "Esperanto", - "est": "Estónio", - "ewe": "Ewe", - "ewo": "Ewondo", + "epo": "Эсперанто", + "est": "Эстонский", + "eus": "Баскский", + "ewe": "Эве", + "ewo": "Эвондо", "fan": "Fang (Equatorial Guinea)", - "fat": "Fanti", - "fao": "Faroese", - "fij": "Fijian", + "fao": "Фарерский", + "fas": "Персидский", + "fat": "Фанти", + "fij": "Фиджийский", "fil": "Filipino", - "fin": "Finlandês", - "fon": "Fon", - "fra": "Francês", - "fur": "Friuliano", - "ful": "Fulah", - "gaa": "Ga", - "glg": "Galician", - "lug": "Ganda", - "gay": "Gayo", + "fin": "Финский", + "fon": "Фон", + "fra": "Французский", + "frm": "French; Middle (ca. 1400-1600)", + "fro": "French; Old (842-ca. 1400)", + "frr": "Frisian; Northern", + "frs": "Frisian; Eastern", + "fry": "Frisian; Western", + "ful": "Фулах", + "fur": "Фриулианский", + "gaa": "Га", + "gay": "Гайо", "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", + "gez": "Геэз", + "gil": "Гильбертский", + "gla": "Gaelic; Scottish", + "gle": "Ирландский", + "glg": "Galician", + "glv": "Мэнкский", + "gmh": "German; Middle High (ca. 1050-1500)", + "goh": "German; Old High (ca. 750-1050)", + "gon": "Гонди", + "gor": "Горонтало", + "got": "Готский", + "grb": "Гребо", + "grc": "Древнегреческий (по 1453)", + "grn": "Гуарани", + "gsw": "German; Swiss", + "guj": "Гуджарати", "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", + "hai": "Хайда", + "hat": "Creole; Haitian", + "hau": "Хауса", + "haw": "Гавайский", + "heb": "Иврит", + "her": "Гереро", + "hil": "Хилигайнон", + "hin": "Хинди", + "hit": "Хиттит", + "hmj": "Ge", + "hmn": "Хмонг", + "hmo": "Хири Моту", + "hrv": "Хорватский", + "hsb": "Sorbian; Upper", + "hun": "Венгерский", + "hup": "Хупа", + "hye": "Армянский", + "iba": "Ибанский", + "ibo": "Игбо", + "ido": "Идо", + "iii": "Yi; Sichuan", + "iku": "Инуктитут", + "ile": "Интерлингве", + "ilo": "Илоко", + "ina": "Интерлингва (Ассоциация международного вспомогательного языка)", + "ind": "Индонезийский", + "inh": "Ингушский", + "ipk": "Инулиак", + "isl": "Исландский", + "ita": "Итальянский", + "jav": "Яванский", + "jbo": "Лоджбан", + "jpn": "Японский", + "jpr": "Еврейско-персидский", + "jrb": "Еврейско-арабский", + "kaa": "Каракалпакский", + "kab": "Кабильский", + "kac": "Качинский", "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", + "kam": "Kamba (Kenya)", + "kan": "Каннада", + "kas": "Кашмири", + "kat": "Грузинский", + "kau": "Канури", + "kaw": "Кави", + "kaz": "Казахский", + "kbd": "Кабардинский", + "kha": "Кхаси", + "khm": "Khmer; Central", + "kho": "Хотанский", + "kik": "Кикуйю", + "kin": "Киньяруанда", + "kir": "Киргизский", + "kmb": "Кимбунду", "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", + "kom": "Коми", + "kon": "Конго", + "kor": "Корейский", + "kos": "Косраинский", + "kpe": "Кпелле", + "krc": "Карачаево-балкарский", + "krl": "Карельский", + "kru": "Курух", + "kua": "Киньяма", + "kum": "Кумыкский", + "kur": "Курдский", + "kut": "Кутенаи", + "lad": "Ладино", + "lah": "Лахнда", + "lam": "Ламба", + "lao": "Лаосский", + "lat": "Латинский", + "lav": "Латвийский", + "lez": "Лезгинский", "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", + "lin": "Лингала", + "lit": "Литовский", + "lol": "Монго", + "loz": "Лози", "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)", + "lua": "Луба-Лулуа", + "lub": "Луба-Катанга", + "lug": "Ганда", + "lui": "Луисеньо", + "lun": "Лунда", + "luo": "Луо (Кения и Танзания)", + "lus": "Лушай", + "mad": "Мадурский", + "mag": "Магахи", "mah": "Marshallese", - "mwr": "Marwari", - "mas": "Masai", + "mai": "Майтхили", + "mak": "Макассарский", + "mal": "Малаялам", + "man": "Мандинго", + "mar": "Маратхи", + "mas": "Масаи", + "mdf": "Мокшанский", + "mdr": "Мандарский", "men": "Mende (Sierra Leone)", + "mga": "Среднеирландский (900-1200)", "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", + "min": "Минангкабау", + "mis": "Uncoded languages", + "mkd": "Македонский", + "mlg": "Малагаси", + "mlt": "Мальтийский", + "mnc": "Манчу", + "mni": "Манипури", + "moh": "Мохаук", + "mon": "Монгольский", + "mos": "Моей", + "mri": "Маори", + "msa": "Malay (macrolanguage)", + "mul": "Разных семей языки", + "mus": "Крик", + "mwl": "Мирандские", + "mwr": "Марвари", + "mya": "Бирманский", + "myv": "Эрзянский", + "nap": "Неаполитанский", + "nau": "Науру", "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", + "nbl": "Ндебеле южный", + "nde": "Ндебеле северный", + "ndo": "Ндунга", + "nds": "German; Low", + "nep": "Непальский", + "new": "Bhasa; Nepal", + "nia": "Ниас", + "niu": "Ниуэ", + "nld": "Нидерландский", + "nno": "Норвежский Нюнорск", + "nob": "Norwegian Bokmål", + "nog": "Ногайский", + "non": "Старонорвежский", + "nor": "Норвежский", + "nqo": "Н'ко", + "nso": "Sotho; Northern", + "nwc": "Newari; Old", "nya": "Nyanja", - "nyn": "Nyankole", - "nyo": "Nyoro", - "nzi": "Nzima", + "nym": "Ньямвези", + "nyn": "Ньянколе", + "nyo": "Ньоро", + "nzi": "Нзима", "oci": "Occitan (post 1500)", - "oji": "Ojibwa", - "orm": "Oromo", - "osa": "Osage", + "oji": "Оджибва", + "ori": "Ория", + "orm": "Оромо", + "osa": "Оседжи", "oss": "Ossetian", - "pal": "Pálavi", - "pau": "Palauano", - "pli": "Pali", - "pam": "Pampanga", - "pag": "Pangasinense", + "ota": "Турецкий; Отомангский (1500-1928)", + "pag": "Пангасинан", + "pal": "Пехлевийский", + "pam": "Пампанга", "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", + "pap": "Папьяменто", + "pau": "Палау", + "peo": "Persian; Old (ca. 600-400 B.C.)", + "phn": "Финикийский", + "pli": "Пали", + "pol": "Польский", + "pon": "Фонпейский", + "por": "Португальский", + "pro": "Старопровансальский (по 1500)", + "pus": "Пушту", + "que": "Кечуа", + "raj": "Раджастхани", + "rap": "Рапаню", + "rar": "Maori; Cook Islands", "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", + "rom": "Цыганский", + "ron": "Румынский", + "run": "Рунди", + "rup": "Romanian; Macedo-", + "rus": "Русский", + "sad": "Сандаве", + "sag": "Санго", + "sah": "Якутский", + "sam": "Aramaic; Samaritan", + "san": "Санскрит", + "sas": "Сасакский", + "sat": "Сантали", + "scn": "Сицилийский", + "sco": "Шотландский", + "sel": "Селкапский", + "sga": "Староирландский (по 900)", + "shn": "Шанский", + "sid": "Сидама", + "sin": "Сингальский", + "slk": "Словацкий", + "slv": "Словенский", + "sma": "Sami; Southern", + "sme": "Sami; Northern", + "smj": "Люле-саамский", + "smn": "Sami; Inari", + "smo": "Самоанский", + "sms": "Sami; Skolt", + "sna": "Шона", + "snd": "Синдхи", + "snk": "Сонинк", + "sog": "Согдийский", + "som": "Сомали", + "sot": "Сото Южный", + "spa": "Испанский", + "sqi": "Албанский", + "srd": "Сардинский", "srn": "Sranan Tongo", - "suk": "Sukuma", - "sux": "Sumerian", - "sun": "Sudanês", - "sus": "Sosso", + "srp": "Сербский", + "srr": "Серер", + "ssw": "Свати", + "suk": "Сукума", + "sun": "Сунданский", + "sus": "Сусу", + "sux": "Шумерский", "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", + "swe": "Шведский", + "syc": "Syriac; Classical", + "syr": "Сирийский", + "tah": "Таитянский", + "tam": "Тамильский", + "tat": "Татарский", + "tel": "Телугу", + "tem": "Темне", + "ter": "Терено", + "tet": "Тетумский", + "tgk": "Таджикский", + "tgl": "Тагалог", + "tha": "Таи", + "tig": "Тигре", + "tir": "Тигринья", + "tiv": "Тив", + "tkl": "Токелау", + "tlh": "Klingon", + "tli": "Тлингит", + "tmh": "Тамашек", + "tog": "Тонга (Ньяса)", + "ton": "Тонга (острова Тонга)", + "tpi": "Ток Писин", + "tsi": "Цимшиан", + "tsn": "Тсвана", + "tso": "Тсонга", + "tuk": "Туркменский", + "tum": "Тумбука", + "tur": "Турецкий", + "tvl": "Тувалу", + "twi": "Тви", + "tyv": "Тувинский", + "udm": "Удмуртский", + "uga": "Угаритский", + "uig": "Уйгурский", + "ukr": "Украинский", + "umb": "Умбунду", + "und": "Неидентифицированный", + "urd": "Урду", + "uzb": "Узбекский", + "vai": "Ваи", + "ven": "Венда", + "vie": "Вьетнамский", + "vol": "Волапюк", + "vot": "Вотик", "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" + "war": "Waray (Philippines)", + "was": "Вашо", + "wln": "Валлун", + "wol": "Волоф", + "xal": "Kalmyk", + "xho": "Коса", + "yao": "Яо", + "yap": "Яапийский", + "yid": "Идиш", + "yor": "Йоруба", + "zap": "Сапотекский", + "zbl": "Blissymbols", + "zen": "Зенагский", + "zha": "Чжуанский", + "zho": "Китайский", + "zul": "Зулусский", + "zun": "Зуньи", + "zxx": "Нет языкового содержимого", + "zza": "Зазаки" }, - "ru": { - "aar": "Афар", - "abk": "Абхазский", - "ace": "Ачехский", - "ach": "Ачоли", - "ada": "Адангме", - "ady": "Адыгейский", - "afh": "Африхили", - "afr": "Африкаанс", + "sk": { + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Afrikánsky", "ain": "Ainu (Japan)", - "aka": "Акан", - "akk": "Аккадский", - "ale": "Алеутский", - "alt": "Altai; Southern", - "amh": "Амхарский (Амаринья)", - "ang": "English; Old (ca. 450-1100)", - "anp": "Анжика", - "ara": "Арабский", - "arc": "Арамейский; Официальный", - "arg": "Арагонский", - "arn": "Mapudungun", - "arp": "Арапахо", - "arw": "Аравакский", - "asm": "Ассамский", - "ast": "Астурийский", - "ava": "Аварский", - "ave": "Авестийский", - "awa": "Авадхи", - "aym": "Аймара", - "aze": "Азербайджанский", - "bak": "Башкирский", + "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": "Бамбара", - "ban": "Балийский", - "bas": "Баса (Камерун)", - "bej": "Беджа", - "bel": "Белорусский", - "bem": "Бемба (Замбия)", - "ben": "Бенгальский", - "bho": "Бходжпури", - "bik": "Бикольский", - "bin": "Бини", - "bis": "Бислама", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Bashkir", + "eus": "Baskitský", + "bej": "Beja", + "bel": "Belarusian", + "bem": "Bemba (Zambia)", + "ben": "Bengali", "bit": "Berinomo", - "bla": "Сиксика", - "bod": "Тибетский", - "bos": "Боснийский", - "bra": "Браун", - "bre": "Бретонский", - "bua": "Бурятский", - "bug": "Бугийский", - "bul": "Болгарский", + "bho": "Bhojpuri", + "bik": "Bikol", "byn": "Bilin", - "cad": "Каддо", - "car": "Carib; Galibi", - "cat": "Каталанский", - "ceb": "Себуано", - "ces": "Чешский", - "cha": "Чаморро", - "chb": "Чибча", - "che": "Чеченский", - "chg": "Чагатайский", - "chk": "Трукский", - "chm": "Марийский (Россия)", - "chn": "Чинук жаргон", - "cho": "Чоктав", - "chp": "Чипевианский", - "chr": "Чероки", + "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", - "chu": "Slavonic; Old", - "chv": "Чувашский", - "chy": "Чейенн", - "cop": "Коптский", - "cor": "Корнский", - "cos": "Корсиканский", - "cre": "Кри", - "crh": "Turkish; Crimean", - "csb": "Кашубианский", - "cym": "Уэльский (Валлийский)", - "dak": "Дакота", - "dan": "Датский", - "dar": "Даргва", - "del": "Делаварский", - "den": "Атапачские языки", - "deu": "Немецкий", - "dgr": "Догриб", - "din": "Динка", + "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)", - "dsb": "Sorbian; Lower", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Holandský", "dse": "Dutch Sign Language", - "dua": "Дуала", - "dum": "Dutch; Middle (ca. 1050-1350)", - "dyu": "Диула (Дьюла)", - "dzo": "Дзонг-кэ", - "efi": "Эфик", - "egy": "Древнеегипетский", - "eka": "Экаджук", - "ell": "Новогреческий (с 1453)", - "elx": "Эламский", - "eng": "Английский", - "enm": "Среднеанглийский (1100-1500)", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Egyptian (Ancient)", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Angličtina", "enu": "Enu", - "epo": "Эсперанто", - "est": "Эстонский", - "eus": "Баскский", - "ewe": "Эве", - "ewo": "Эвондо", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estónsky", + "ewe": "Ewe", + "ewo": "Ewondo", "fan": "Fang (Equatorial Guinea)", - "fao": "Фарерский", - "fas": "Персидский", - "fat": "Фанти", - "fij": "Фиджийский", + "fat": "Fanti", + "fao": "Faroese", + "fij": "Fijian", "fil": "Filipino", - "fin": "Финский", - "fon": "Фон", - "fra": "Французский", - "frm": "French; Middle (ca. 1400-1600)", - "fro": "French; Old (842-ca. 1400)", - "frr": "Frisian; Northern", - "frs": "Frisian; Eastern", - "fry": "Frisian; Western", - "ful": "Фулах", - "fur": "Фриулианский", - "gaa": "Га", - "gay": "Гайо", - "gba": "Gbaya (Central African Republic)", - "gez": "Геэз", - "gil": "Гильбертский", - "gla": "Gaelic; Scottish", - "gle": "Ирландский", + "fin": "Fínsky", + "fon": "Fon", + "fra": "Francúzsky", + "fur": "Friulian", + "ful": "Fulah", + "gaa": "Ga", "glg": "Galician", - "glv": "Мэнкский", - "gmh": "German; Middle High (ca. 1050-1500)", - "goh": "German; Old High (ca. 750-1050)", - "gon": "Гонди", - "gor": "Горонтало", - "got": "Готский", - "grb": "Гребо", - "grc": "Древнегреческий (по 1453)", - "grn": "Гуарани", - "gsw": "German; Swiss", - "guj": "Гуджарати", - "gwi": "Gwichʼin", - "hai": "Хайда", - "hat": "Creole; Haitian", - "hau": "Хауса", - "haw": "Гавайский", - "heb": "Иврит", - "her": "Гереро", - "hil": "Хилигайнон", - "hin": "Хинди", - "hit": "Хиттит", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", "hmj": "Ge", - "hmn": "Хмонг", - "hmo": "Хири Моту", - "hrv": "Хорватский", - "hsb": "Sorbian; Upper", - "hun": "Венгерский", - "hup": "Хупа", - "hye": "Армянский", - "iba": "Ибанский", - "ibo": "Игбо", - "ido": "Идо", - "iii": "Yi; Sichuan", - "iku": "Инуктитут", - "ile": "Интерлингве", - "ilo": "Илоко", - "ina": "Интерлингва (Ассоциация международного вспомогательного языка)", - "ind": "Индонезийский", - "inh": "Ингушский", - "ipk": "Инулиак", - "isl": "Исландский", - "ita": "Итальянский", - "jav": "Яванский", - "jbo": "Лоджбан", - "jpn": "Японский", - "jpr": "Еврейско-персидский", - "jrb": "Еврейско-арабский", - "kaa": "Каракалпакский", - "kab": "Кабильский", - "kac": "Качинский", + "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": "Каннада", - "kas": "Кашмири", - "kat": "Грузинский", - "kau": "Канури", - "kaw": "Кави", - "kaz": "Казахский", - "kbd": "Кабардинский", - "kha": "Кхаси", - "khm": "Khmer; Central", - "kho": "Хотанский", - "kik": "Кикуйю", - "kin": "Киньяруанда", - "kir": "Киргизский", - "kmb": "Кимбунду", + "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)", - "kom": "Коми", - "kon": "Конго", - "kor": "Корейский", - "kos": "Косраинский", - "kpe": "Кпелле", - "krc": "Карачаево-балкарский", - "krl": "Карельский", - "kru": "Курух", - "kua": "Киньяма", - "kum": "Кумыкский", - "kur": "Курдский", - "kut": "Кутенаи", - "lad": "Ладино", - "lah": "Лахнда", - "lam": "Ламба", - "lao": "Лаосский", - "lat": "Латинский", - "lav": "Латвийский", - "lez": "Лезгинский", + "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": "Лингала", - "lit": "Литовский", - "lol": "Монго", - "loz": "Лози", + "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", - "lua": "Луба-Лулуа", - "lub": "Луба-Катанга", - "lug": "Ганда", - "lui": "Луисеньо", - "lun": "Лунда", - "luo": "Луо (Кения и Танзания)", - "lus": "Лушай", - "mad": "Мадурский", - "mag": "Магахи", + "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", - "mai": "Майтхили", - "mak": "Макассарский", - "mal": "Малаялам", - "man": "Мандинго", - "mar": "Маратхи", - "mas": "Масаи", - "mdf": "Мокшанский", - "mdr": "Мандарский", + "mwr": "Marwari", + "mas": "Masai", "men": "Mende (Sierra Leone)", - "mga": "Среднеирландский (900-1200)", "mic": "Mi'kmaq", - "min": "Минангкабау", - "mis": "Uncoded languages", - "mkd": "Македонский", - "mlg": "Малагаси", - "mlt": "Мальтийский", - "mnc": "Манчу", - "mni": "Манипури", - "moh": "Мохаук", - "mon": "Монгольский", - "mos": "Моей", - "mri": "Маори", - "msa": "Malay (macrolanguage)", - "mul": "Разных семей языки", - "mus": "Крик", - "mwl": "Мирандские", - "mwr": "Марвари", - "mya": "Бирманский", - "myv": "Эрзянский", - "nap": "Неаполитанский", - "nau": "Науру", + "min": "Minangkabau", + "mwl": "Mirandese", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Multiple languages", + "nqo": "N'Ko", + "nau": "Nauru", "nav": "Navajo", - "nbl": "Ндебеле южный", - "nde": "Ндебеле северный", - "ndo": "Ндунга", - "nds": "German; Low", - "nep": "Непальский", - "new": "Bhasa; Nepal", - "nia": "Ниас", - "niu": "Ниуэ", - "nld": "Нидерландский", - "nno": "Норвежский Нюнорск", - "nob": "Norwegian Bokmål", - "nog": "Ногайский", - "non": "Старонорвежский", - "nor": "Норвежский", - "nqo": "Н'ко", - "nso": "Sotho; Northern", - "nwc": "Newari; Old", - "nya": "Nyanja", - "nym": "Ньямвези", - "nyn": "Ньянколе", - "nyo": "Ньоро", - "nzi": "Нзима", - "oci": "Occitan (post 1500)", - "oji": "Оджибва", - "ori": "Ория", - "orm": "Оромо", - "osa": "Оседжи", - "oss": "Ossetian", - "ota": "Турецкий; Отомангский (1500-1928)", - "pag": "Пангасинан", - "pal": "Пехлевийский", - "pam": "Пампанга", - "pan": "Panjabi", - "pap": "Папьяменто", - "pau": "Палау", - "peo": "Persian; Old (ca. 600-400 B.C.)", - "phn": "Финикийский", - "pli": "Пали", - "pol": "Польский", - "pon": "Фонпейский", - "por": "Португальский", - "pro": "Старопровансальский (по 1500)", - "pus": "Пушту", - "que": "Кечуа", - "raj": "Раджастхани", - "rap": "Рапаню", - "rar": "Maori; Cook Islands", - "roh": "Romansh", - "rom": "Цыганский", - "ron": "Румынский", - "run": "Рунди", - "rup": "Romanian; Macedo-", - "rus": "Русский", - "sad": "Сандаве", - "sag": "Санго", - "sah": "Якутский", - "sam": "Aramaic; Samaritan", - "san": "Санскрит", - "sas": "Сасакский", - "sat": "Сантали", - "scn": "Сицилийский", - "sco": "Шотландский", - "sel": "Селкапский", - "sga": "Староирландский (по 900)", - "shn": "Шанский", - "sid": "Сидама", - "sin": "Сингальский", - "slk": "Словацкий", - "slv": "Словенский", - "sma": "Sami; Southern", - "sme": "Sami; Northern", - "smj": "Люле-саамский", - "smn": "Sami; Inari", - "smo": "Самоанский", - "sms": "Sami; Skolt", - "sna": "Шона", - "snd": "Синдхи", - "snk": "Сонинк", - "sog": "Согдийский", - "som": "Сомали", - "sot": "Сото Южный", - "spa": "Испанский", - "sqi": "Албанский", - "srd": "Сардинский", + "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", - "srp": "Сербский", - "srr": "Серер", - "ssw": "Свати", - "suk": "Сукума", - "sun": "Сунданский", - "sus": "Сусу", - "sux": "Шумерский", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sundanese", + "sus": "Susu", "swa": "Swahili (macrolanguage)", - "swe": "Шведский", - "syc": "Syriac; Classical", - "syr": "Сирийский", - "tah": "Таитянский", - "tam": "Тамильский", - "tat": "Татарский", - "tel": "Телугу", - "tem": "Темне", - "ter": "Терено", - "tet": "Тетумский", - "tgk": "Таджикский", - "tgl": "Тагалог", - "tha": "Таи", - "tig": "Тигре", - "tir": "Тигринья", - "tiv": "Тив", - "tkl": "Токелау", - "tlh": "Klingon", - "tli": "Тлингит", - "tmh": "Тамашек", - "tog": "Тонга (Ньяса)", - "ton": "Тонга (острова Тонга)", - "tpi": "Ток Писин", - "tsi": "Цимшиан", - "tsn": "Тсвана", - "tso": "Тсонга", - "tuk": "Туркменский", - "tum": "Тумбука", - "tur": "Турецкий", - "tvl": "Тувалу", - "twi": "Тви", - "tyv": "Тувинский", - "udm": "Удмуртский", - "uga": "Угаритский", - "uig": "Уйгурский", - "ukr": "Украинский", - "umb": "Умбунду", - "und": "Неидентифицированный", - "urd": "Урду", - "uzb": "Узбекский", - "vai": "Ваи", - "ven": "Венда", - "vie": "Вьетнамский", - "vol": "Волапюк", - "vot": "Вотик", - "wal": "Wolaytta", + "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": "Вашо", - "wln": "Валлун", - "wol": "Волоф", - "xal": "Kalmyk", - "xho": "Коса", - "yao": "Яо", - "yap": "Яапийский", - "yid": "Идиш", - "yor": "Йоруба", - "zap": "Сапотекский", - "zbl": "Blissymbols", - "zen": "Зенагский", - "zha": "Чжуанский", - "zho": "Китайский", - "zul": "Зулусский", - "zun": "Зуньи", - "zxx": "Нет языкового содержимого", - "zza": "Зазаки" + "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", @@ -7476,6 +9366,384 @@ LANGUAGE_NAMES = { "zxx": "немає мовних даних", "zza": "заза" }, + "vi": { + "abk": "Abkhazian", + "ace": "Tiếng A-chinh", + "ach": "Tiếng A-co-li", + "ada": "Tiếng A-đang-me", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Tiếng A-phi-li", + "afr": "Tiếng Hà Lan-Nam Phi", + "ain": "Ainu (Japan)", + "aka": "Akan", + "akk": "Tiếng A-ca-đi", + "sqi": "Tiếng An-ba-ni", + "ale": "Tiếng A-le-uth", + "amh": "Tiếng Am-ha-ri", + "anp": "Tiếng An-gi-ca", + "ara": "Tiếng A-rập", + "arg": "Tiếng A-ra-got", + "arp": "Tiếng A-ra-bô", + "arw": "Tiếng A-ra-ouac", + "hye": "Tiếng Ác-mê-ni", + "asm": "Tiếng A-xam", + "ast": "Asturian", + "ava": "Tiếng A-va-ri", + "ave": "Tiếng A-ve-x-tan", + "awa": "Tiếng A-oua-đi", + "aym": "Aymara", + "aze": "Tiếng Agiecbaigiăng", + "ban": "Tiếng Ba-li", + "bal": "Tiếng Ba-lu-khi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Tiếng Ba-s-kic", + "eus": "Tiếng Baxcơ", + "bej": "Tiếng Be-gia", + "bel": "Tiếng Be-la-ruxợ", + "bem": "Bemba (Zambia)", + "ben": "Tiếng Băng Gan", + "bit": "Berinomo", + "bho": "Tiếng Bo-giơ-pu-ri", + "bik": "Tiếng Bi-cot", + "byn": "Bilin", + "bin": "Tiếng Bi-ni", + "bis": "Tiếng Bix-la-ma", + "zbl": "Blissymbols", + "bos": "Tiếng Bô-xni-a", + "bra": "Tiếng Boua-giơ", + "bre": "Tiếng Boue-ton (Pháp)", + "bug": "Tiếng Bu-gin", + "bul": "Tiếng Bảo Gai Lơi", + "bua": "Tiếng Bu-ri-at", + "mya": "Tiếng Miến Điện", + "cad": "Tiếng Ca-đô", + "cat": "Tiếng Catalăng", + "ceb": "Tiếng Xe-bu-a-nô", + "chg": "Chagatai", + "cha": "Tiếng Cha-mo-ro", + "che": "Tiếng Che-chẹnh", + "chr": "Tiếng Che-rô-ki", + "chy": "Tiếng Chê-iênh", + "chb": "Tiếng Chic-cha", + "zho": "Tiếng Trung Hoa", + "chn": "Biệt ngữ Chi-nukh", + "chp": "Tiếng Chi-pu-i-a", + "cho": "Tiếng Choc-toa", + "cht": "Cholón", + "chk": "Tiếng Chu-ki", + "chv": "Tiếng Chu-vaxơ", + "cop": "Ngôn ngữ phổ biến trong Giáo hội Ai Cập", + "cor": "Tiếng Khonh-uoă", + "cos": "Tiếng Kho-si-ca", + "cre": "Tiếng Kh-ri", + "mus": "Tiếng C-ric", + "hrv": "Tiếng Crô-át", + "ces": "Tiếng Séc", + "dak": "Tiếng Đa-cô-ta", + "dan": "Tiếng Đan Mạch", + "dar": "Tiếng Đac-oua", + "del": "Tiếng Đe-la-oue", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Tiếng Đoc-ric", + "dua": "Tiếng Đu-a-la", + "nld": "Tiếng Hòa Lan", + "dse": "Dutch Sign Language", + "dyu": "Tiếng Đi-u-la", + "dzo": "Tiếng Đxong-kha", + "efi": "Tiếng E-phic", + "egy": "Tiếng Ai Cập (cổ)", + "eka": "Tiếng E-ca-giuc", + "elx": "Tiếng E-la-mi", + "eng": "Tiếng Anh", + "enu": "Enu", + "myv": "Tiếng Ơ-dia", + "epo": "Tiếng Etpêrantô", + "est": "Tiếng Phổ Cổ", + "ewe": "Tiếng E-oue", + "ewo": "Tiếng E-ouon-đô", + "fan": "Fang (Equatorial Guinea)", + "fat": "Tiếng Phan-ti", + "fao": "Tiếng Pha-rô", + "fij": "Tiếng Phi-gi", + "fil": "Filipino", + "fin": "Tiếng Phần Lan", + "fon": "Tiếng Phonh", + "fra": "Tiếng Pháp", + "fur": "Tiếng Ph-riu-li", + "ful": "Tiếng Phu-la", + "gaa": "Tiếng Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Tiếng Gay-ô", + "gba": "Gbaya (Central African Republic)", + "hmj": "Ge", + "gez": "Tiếng Gi-d", + "kat": "Tiếng Gi-oa-gi-a", + "deu": "Tiếng Đức", + "gil": "Tiếng Gil-bơt", + "gon": "Tiếng Gon-đi", + "gor": "Tiếng Go-ron-ta-lô", + "got": "Tiếng Gô-tích", + "grb": "Tiếng Goue-bô", + "grn": "Tiếng Gua-ra-ni", + "guj": "Tiếng Gu-gia-ra-ti", + "gwi": "Gwichʼin", + "hai": "Tiếng Hai-đa", + "hau": "Tiếng Hau-xa", + "haw": "Tiếng Ha-uoai-i", + "heb": "Tiếng Do Thái", + "her": "Tiếng He-re-rô", + "hil": "Tiếng Hi-li-gay-non", + "hin": "Tiếng Hin-đi", + "hmo": "Tiếng Mo-tu", + "hit": "Tiếng Hic-tic", + "hmn": "Tiếng Miêu", + "hun": "Tiếng Hung Gia Lợi", + "hup": "Tiếng Hu-pa", + "iba": "Iban", + "isl": "Tiếng Băng đảo", + "ido": "Tiếng I-đô", + "ibo": "Tiếng Ic-bô", + "ilo": "Tiếng I-lô-cô", + "ind": "Tiếng Nam Dương", + "inh": "Tiếng In-gut", + "ina": "Ngôn ngữ lẫn nhau In-tơ-lin-gua (Liên Hiệp Ngôn Ngữ Bổ Trợ Quốc Tế)", + "ile": "Ngôn ngữ lẫn nhau In-tơ-ling", + "iku": "Tiếng I-nuc-ti-tuc", + "ipk": "Tiếng In-u-bơ-lac", + "gle": "Tiếng Ái Nhĩ Lan", + "ita": "Tiếng Ý", + "jpn": "Tiếng Nhật", + "jav": "Tiếng Gia-va", + "jrb": "Do thái - A-rập", + "jpr": "Do thái - Ba tư", + "kbd": "Tiếng Ca-bat", + "kab": "Tiếng Ca-bai", + "kac": "Tiếng Ca-chin", + "kal": "Kalaallisut", + "xal": "Kalmyk", + "kam": "Kamba (Kenya)", + "kan": "Tiếng Kan-na-đa", + "kau": "Tiếng Ca-nu-ri", + "kaa": "Tiếng Ca-ra-Cac-pac", + "krc": "Tiếng Ca-ra-chay-Boa-ca", + "krl": "Tiếng Ca-re-ni", + "kas": "Tiếng Ca-s-mi-ri", + "csb": "Tiếng Ca-su-bi", + "kaw": "Tiếng Ca-oui", + "kaz": "Tiếng Ca-dakh", + "kha": "Khasi", + "kho": "Tiếng Kho-tan", + "kik": "Tiếng Khi-ku-iu", + "kmb": "Tiếng Kim-bun-đu", + "kin": "Tiếng Kin-ia-ouanh-đa", + "kir": "Tiếng Kit-ki-dơ", + "tlh": "Klingon", + "kom": "Tiếng Cô-mi", + "kon": "Kongo", + "kok": "Konkani (macrolanguage)", + "kor": "Tiếng Hàn Quốc", + "kos": "Tiếng Co-x-rai", + "kpe": "Tiếng C-pe-le", + "kua": "Tiếng Cu-an-i-am-a", + "kum": "Tiếng Cu-mic", + "kur": "Tiếng người Kurd", + "kru": "Tiếng Cu-ruc", + "kut": "Tiếng Cu-ten-ai", + "lad": "Tiếng La-đi-nô", + "lah": "Tiếng Lan-đa", + "lam": "Tiếng Lam-ba", + "lao": "Tiếng Lào", + "lat": "Tiếng La-tinh", + "lav": "Tiếng Lát-vi-a", + "lez": "Tiếng Le-d-khi-an", + "lim": "Limburgan", + "lin": "Tiếng Lin-ga-la", + "lit": "Tiếng Li-tu-a-ni", + "jbo": "Tiếng Loc-ba", + "loz": "Tiếng Lo-di", + "lub": "Tiếng Lu-ba-Ca-tan-ga", + "lua": "Tiếng Lu-ba-Lu-lu-a", + "lui": "Tiếng Lui-xen-ô", + "smj": "Tiếng Sa-mi Lu-le", + "lun": "Tiếng Lun-đa", + "luo": "Tiếng Luo (Ken-i-a và Than-dê-ni-a)", + "lus": "Tiếng Lu-sai", + "ltz": "Luxembourgish", + "mkd": "Tiếng Maxêđôni", + "mad": "Tiếng Ma-đu-ri", + "mag": "Tiếng Mu-ga-hi", + "mai": "Tiếng Mai-ti-li", + "mak": "Makasar", + "mlg": "Tiếng Ma-la-ga-si", + "msa": "Malay (macrolanguage)", + "mal": "Tiếng Ma-lay-am", + "mlt": "Tiếng Mantơ", + "mnc": "Tiếng Man-chu (Trung Hoa)", + "mdr": "Tiếng Man-đa", + "man": "Tiếng Man-đin-gô", + "mni": "Tiếng Ma-ni-pu-ri", + "glv": "Tiếng Man-khơx", + "mri": "Tiếng Maori", + "arn": "Mapudungun", + "mar": "Tiếng Ma-ra-ti", + "chm": "Mari (Russia)", + "mah": "Marshallese", + "mwr": "Tiếng Ma-oua-ri", + "mas": "Tiếng Ma-sai", + "men": "Mende (Sierra Leone)", + "mic": "Mi'kmaq", + "min": "Tiếng Mi-nang-ca-bau", + "mwl": "Tiếng Mi-ran-đi", + "moh": "Tiếng Mô-hoakh", + "mdf": "Tiếng Moc-sa", + "lol": "Tiếng Mon-gô", + "mon": "Tiếng Mông Cổ", + "mos": "Tiếng Mo-xi", + "mul": "Đa ngôn ngữ", + "nqo": "N'Ko", + "nau": "Tiếng Nau-ru", + "nav": "Navajo", + "ndo": "Tiếng N-đon-ga", + "nap": "Tiếng Na-po-li (Ý)", + "nia": "Tiếng Ni-at", + "niu": "Tiếng Niu-i", + "zxx": "Không có nội dung kiểu ngôn ngữ", + "nog": "Tiếng No-gai", + "nor": "Tiếng Na-uy", + "nob": "Norwegian Bokmål", + "nno": "Tiếng Na-uy (Nynorsk)", + "nym": "Tiếng Nai-am-oue-di", + "nya": "Nyanja", + "nyn": "Tiếng Nai-an-co-le", + "nyo": "Nyoro", + "nzi": "Tiếng N-di-ma", + "oci": "Occitan (post 1500)", + "oji": "Ojibwa", + "orm": "Tiếng O-ro-mô", + "osa": "Tiếng O-sa-ge", + "oss": "Ossetian", + "pal": "Tiếng Pa-la-vi", + "pau": "Tiếng Pa-lau-a", + "pli": "Pali", + "pam": "Tiếng Pam-pan-ga", + "pag": "Tiếng Pan-ga-sin", + "pan": "Panjabi", + "pap": "Tiếng Pa-pi-a-men-tô", + "fas": "Tiếng Ba Tư", + "phn": "Tiếng Phê-ni-xi", + "pon": "Tiếng Pon-pê-i-a", + "pol": "Tiếng Ba Lan", + "por": "Tiếng Bồ Đào Nha", + "pus": "Tiếng Pu-s-tô", + "que": "Quechua", + "raj": "Tiếng Ra-gia-x-tni", + "rap": "Tiếng Ra-pa-nui", + "ron": "Tiếng Lỗ Má Ni", + "roh": "Romansh", + "rom": "Tiếng Gipxi", + "run": "Tiếng Run-đi", + "rus": "Tiếng Nga", + "smo": "Tiếng Xa-mô-a", + "sad": "Tiếng San-đa-ouê", + "sag": "Sango", + "san": "Tiếng Phạn", + "sat": "Tiếng San-ta-li", + "srd": "Tiếng Xa-đi-ni-a (Ý)", + "sas": "Sasak", + "sco": "Tiếng Ê-cốt", + "sel": "Tiếng Xe-cuc", + "srp": "Tiếng Xéc bi", + "srr": "Serer", + "shn": "Tiếng San", + "sna": "Tiếng Sô-na", + "scn": "Tiếng Xi-xi-li", + "sid": "Tiếng Xi-đa-mô", + "bla": "Tiếng Xich-xich-a", + "snd": "Tiếng Sin-đi", + "sin": "Sinhala", + "den": "Tiếng A-ta-pax-ca", + "slk": "Tiếng Xlô-vác", + "slv": "Tiếng Xlô-ven", + "sog": "Tiếng Xoc-đi-a", + "som": "Tiếng Xô-ma-li", + "snk": "Tiếng Xo-nin-khe", + "spa": "Tiếng Tây Ban Nha", + "srn": "Sranan Tongo", + "suk": "Tiếng Xu-ku-ma", + "sux": "Tiếng Xu-me", + "sun": "Tiếng Xunh-đan", + "sus": "Tiếng xu-xu", + "swa": "Swahili (macrolanguage)", + "ssw": "Tiếng Xôa-thi", + "swe": "Tiếng Thuỵ Điển", + "syr": "Tiếng Xi-ri", + "tgl": "Tiếng Ta-ga-lọc", + "tah": "Tiếng Ta-hi-ti", + "tgk": "Tiếng Ta-gic", + "tmh": "Tamashek", + "tam": "Tiếng Ta-mil", + "tat": "Tiếng Tác-ta", + "tel": "Telugu", + "ter": "Tiếng Te-re-no", + "tet": "Tiếng Te-tum", + "tha": "Tiếng Thái Lan", + "bod": "Tiếng Tây Tạng", + "tig": "Tiếng Thi-gơ-rơ", + "tir": "Tiếng Thi-gơ-rin-ya", + "tem": "Tiếng Tim-ne", + "tiv": "Tiếng Ti-ph", + "tli": "Tiếng Tợ-lin-git", + "tpi": "Tiếng Tok Pi-sin", + "tkl": "Tiếng To-ke-lau", + "tog": "Tiếng Ton-ga (Nai-a-sa)", + "ton": "Tiếng Ton-ga (Quần đảo Ton-ga)", + "tsi": "Tiếng T-xim-si-an", + "tso": "Tiếng Xông-ga", + "tsn": "Tiếng T-xoua-na", + "tum": "Tiếng Tum-bu-ka", + "tur": "Tiếng Thổ Nhĩ Kỳ", + "tuk": "Tiếng Tuơkh-men", + "tvl": "Tiếng Tu-va-lu", + "tyv": "Tiếng Tu-vi-ni", + "twi": "Tiếng Toui", + "udm": "Tiếng Ud-mợt", + "uga": "Tiếng U-ga-ri", + "uig": "Tiếng Ui-guơ", + "ukr": "Tiếng Ukraina", + "umb": "Tiếng Um-bun-đu", + "mis": "Uncoded languages", + "und": "Chưa quyết định", + "urd": "Tiếng Uơ-đu", + "uzb": "Tiếng U-dơ-bếch", + "vai": "Tiếng Vai", + "ven": "Tiếng Ven-đa", + "vie": "Tiếng Việt", + "vol": "Tiếng Vo-la-puk", + "vot": "Tiếng Vo-tic", + "wln": "Tiếng Oua-lon", + "war": "Waray (Philippines)", + "was": "Tiếng Oua-sô", + "cym": "Tiếng Oue-l-s", + "wal": "Wolaytta", + "wol": "Tiếng Ou-o-loc", + "xho": "Tiếng X-hô-da", + "sah": "Tiếng Ia-cut", + "yao": "Tiếng Yao", + "yap": "Tiếng Yat", + "yid": "Tiếng Y-đit", + "yor": "Tiếng Yo-ru-ba", + "zap": "Zapotec", + "zza": "Zaza", + "zen": "Tiếng De-na-ga", + "zha": "Zhuang", + "zul": "Tiếng Du-lu", + "zun": "Tiếng Du-ni" + }, "zh_Hans_CN": { "aar": "阿法尔语", "abk": "阿布哈兹语", diff --git a/cps/kobo.py b/cps/kobo.py index 46e68acb..00e40b49 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 @@ -45,7 +46,9 @@ import requests from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub, csrf, kobo_sync_status -from .constants import sqlalchemy_version2, COVER_THUMBNAIL_SMALL +from . import isoLanguages +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 @@ -53,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 @@ -134,11 +137,15 @@ def convert_to_kobo_timestamp_string(timestamp): @kobo.route("/v1/library/sync") @requires_kobo_auth -@download_required +# @download_required def HandleSyncRequest(): + if not current_user.role_download(): + log.info("Users need download permissions for syncing library to Kobo reader") + return abort(403) sync_token = SyncToken.SyncToken.from_headers(request.headers) - log.info("Kobo library sync request received.") + 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') @@ -155,23 +162,17 @@ def HandleSyncRequest(): new_archived_last_modified = datetime.datetime.min sync_results = [] - # We reload the book database so that the user get's a fresh view of the library + # We reload the book database so that the user gets a fresh view of the library # in case of external changes (e.g: adding a book through Calibre). calibre_db.reconnect_db(config, ub.app_DB_path) 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)) @@ -188,12 +189,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)) @@ -205,15 +203,12 @@ 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] if 'KEPUB' not in formats and config.config_kepubifypath and 'EPUB' in formats: - helper.convert_book_format(book.Books.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.name) + helper.convert_book_format(book.Books.id, config.get_book_path(), 'EPUB', 'KEPUB', current_user.name) kobo_reading_state = get_or_create_reading_state(book.Books.id) entitlement = { @@ -226,7 +221,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) @@ -239,7 +234,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( @@ -251,27 +246,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)) @@ -334,7 +318,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) @@ -355,7 +339,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) @@ -364,7 +348,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]) @@ -376,13 +360,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, ) @@ -443,6 +427,12 @@ def get_seriesindex(book): return book.series_index or 1 +def get_language(book): + if not book.languages: + return 'en' + return isoLanguages.get(part3=book.languages[0].lang_code).part1 + + def get_metadata(book): download_urls = [] kepub = [data for data in book.data if data.format == 'KEPUB'] @@ -452,16 +442,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 = { @@ -480,7 +475,7 @@ def get_metadata(book): "IsInternetArchive": False, "IsPreOrder": False, "IsSocialEnabled": True, - "Language": "en", + "Language": get_language(book), "PhoneticPronunciations": {}, "PublicationDate": convert_to_kobo_timestamp_string(book.pubdate), "Publisher": {"Imprint": "", "Name": get_publisher(book), }, @@ -508,7 +503,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 handeld 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 @@ -702,20 +697,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): @@ -752,7 +739,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( { @@ -769,7 +756,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) @@ -916,20 +903,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("") @@ -944,7 +937,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 @@ -958,7 +951,7 @@ def HandleBookDeletionRequest(book_uuid): @csrf.exempt @kobo.route("/v1/library/", methods=["DELETE", "GET"]) def HandleUnimplementedRequest(dummy=None): - log.debug("Unimplemented Library Request received: %s", request.base_url) + log.debug("Unimplemented Library Request received: %s (request is forwarded to kobo if configured)", request.base_url) return redirect_or_proxy_request() @@ -969,8 +962,9 @@ 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.base_url) + log.debug("Unimplemented User Request received: %s (request is forwarded to kobo if configured)", request.base_url) return redirect_or_proxy_request() @@ -1010,7 +1004,7 @@ def handle_getests(): @kobo.route("/v1/affiliate", methods=["GET", "POST"]) @kobo.route("/v1/deals", methods=["GET", "POST"]) def HandleProductsRequest(dummy=None): - log.debug("Unimplemented Products Request received: %s", request.base_url) + log.debug("Unimplemented Products Request received: %s (request is forwarded to kobo if configured)", request.base_url) return redirect_or_proxy_request() @@ -1027,7 +1021,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 9865b993..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() @@ -107,12 +108,12 @@ def generate_auth_token(user_id): for book in books: formats = [data.format for data in book.data] - if not 'KEPUB' in formats and config.config_kepubifypath and 'EPUB' in formats: + if 'KEPUB' not in formats and config.config_kepubifypath and 'EPUB' in formats: helper.convert_book_format(book.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.name) 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 fcc25c27..74f7fb39 100644 --- a/cps/logger.py +++ b/cps/logger.py @@ -54,7 +54,6 @@ class _Logger(logging.Logger): else: self.error(message, *args, **kwargs) - def debug_no_auth(self, message, *args, **kwargs): message = message.strip("\r\n") if message.startswith("send: AUTH"): @@ -66,6 +65,7 @@ class _Logger(logging.Logger): def get(name=None): return logging.getLogger(name) + def create(): parent_frame = inspect.stack(0)[1] if hasattr(parent_frame, 'frame'): @@ -75,9 +75,11 @@ def create(): parent_module = inspect.getmodule(parent_frame) return get(parent_module.__name__) + def is_debug_enabled(): return logging.root.level <= logging.DEBUG + def is_info_enabled(logger): return logging.getLogger(logger).level <= logging.INFO @@ -114,10 +116,10 @@ def get_accesslogfile(log_file): def setup(log_file, log_level=None): - ''' + """ Configure the logging output. May be called multiple times. - ''' + """ log_level = log_level or DEFAULT_LOG_LEVEL logging.setLoggerClass(_Logger) logging.getLogger(__package__).setLevel(log_level) @@ -127,7 +129,7 @@ def setup(log_file, log_level=None): # avoid spamming the log with debug messages from libraries r.setLevel(log_level) - # Otherwise name get's destroyed on windows + # Otherwise, name gets destroyed on Windows if log_file != LOG_TO_STDERR and log_file != LOG_TO_STDOUT: log_file = _absolute_log_file(log_file, DEFAULT_LOG_FILE) @@ -148,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') @@ -159,13 +161,14 @@ def setup(log_file, log_level=None): r.removeHandler(h) h.close() r.addHandler(file_handler) + logging.captureWarnings(True) return "" if log_file == DEFAULT_LOG_FILE else log_file def create_access_log(log_file, log_name, formatter): - ''' + """ One-time configuration for the web server's access log. - ''' + """ log_file = _absolute_log_file(log_file, DEFAULT_ACCESS_LOG) logging.debug("access log: %s", log_file) @@ -174,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') @@ -182,8 +185,7 @@ def create_access_log(log_file, log_name, formatter): file_handler.setFormatter(formatter) access_log.addHandler(file_handler) - return access_log, \ - "" if _absolute_log_file(log_file, DEFAULT_ACCESS_LOG) == DEFAULT_ACCESS_LOG else log_file + return access_log, "" if _absolute_log_file(log_file, DEFAULT_ACCESS_LOG) == DEFAULT_ACCESS_LOG else log_file # Enable logging of smtp lib debug output 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/metadata_provider/scholar.py b/cps/metadata_provider/scholar.py index 7feb0ee9..5f632343 100644 --- a/cps/metadata_provider/scholar.py +++ b/cps/metadata_provider/scholar.py @@ -49,10 +49,12 @@ class scholar(Metadata): tokens = [quote(t.encode("utf-8")) for t in title_tokens] query = " ".join(tokens) try: + scholarly.set_timeout(20) + scholarly.set_retries(2) scholar_gen = itertools.islice(scholarly.search_pubs(query), 10) except Exception as e: log.warning(e) - return None + return list() for result in scholar_gen: match = self._parse_search_result( result=result, generic_cover="", locale=locale 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..b13b0570 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 @@ -528,7 +502,7 @@ def render_element_index(database_column, linked_table, folder): entries = entries.join(linked_table).join(db.Books) entries = entries.filter(calibre_db.common_filters()).group_by(func.upper(func.substr(database_column, 1, 1))).all() elements = [] - if off == 0: + if off == 0 and entries: elements.append({'id': "00", 'name': _("All")}) shift = 1 for entry in entries[ diff --git a/cps/redirect.py b/cps/redirect.py index 9382a205..09b3101f 100644 --- a/cps/redirect.py +++ b/cps/redirect.py @@ -25,7 +25,7 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# http://flask.pocoo.org/snippets/62/ +# https://web.archive.org/web/20120517003641/http://flask.pocoo.org/snippets/62/ from urllib.parse import urlparse, urljoin diff --git a/cps/remotelogin.py b/cps/remotelogin.py index ea613c29..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 succeded", 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 0750a9c4..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,62 +60,52 @@ 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 -'''def get_readbooks_ids(): - if not config.config_read_column: - readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id))\ - .filter(ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED).all() - return frozenset([x.book_id for x in readBooks]) - else: - try: - readBooks = calibre_db.session.query(db.cc_classes[config.config_read_column])\ - .filter(db.cc_classes[config.config_read_column].value == True).all() - return frozenset([x.book for x in readBooks]) - except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) - return []''' # Returns the template for rendering and includes the instance name def render_title_template(*args, **kwargs): diff --git a/cps/schedule.py b/cps/schedule.py index faadfb7e..bf622b36 100644 --- a/cps/schedule.py +++ b/cps/schedule.py @@ -19,19 +19,26 @@ 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.tempFolder import TaskDeleteTempFolder from .tasks.thumbnail import TaskGenerateCoverThumbnails, TaskGenerateSeriesThumbnails, TaskClearCoverThumbnailCache from .services.worker import WorkerThread - +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]) + # Delete temp folder + tasks.append([lambda: TaskDeleteTempFolder(), 'delete temp', True]) + + # 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 if config.schedule_generate_book_covers: tasks.append([lambda: TaskClearCoverThumbnailCache(0), 'delete superfluous book covers', True]) @@ -62,10 +69,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): @@ -83,6 +90,8 @@ def register_startup_tasks(): # Ignore tasks that should currently be running, as these will be added when registering scheduled tasks if constants.APP_MODE in ['development', 'test'] and not should_task_be_running(start, duration): scheduler.schedule_tasks_immediately(tasks=get_scheduled_tasks(False)) + else: + scheduler.schedule_tasks_immediately(tasks=[[lambda: TaskDeleteTempFolder(), 'delete temp', True]]) def should_task_be_running(start, duration): @@ -91,6 +100,7 @@ def should_task_be_running(start, duration): end_time = start_time + datetime.timedelta(hours=duration // 60, minutes=duration % 60) return start_time < now < end_time + def calclulate_end_time(start, duration): start_time = datetime.datetime.now().replace(hour=start, minute=0) return start_time + datetime.timedelta(hours=duration // 60, minutes=duration % 60) diff --git a/cps/search.py b/cps/search.py index 602881bf..f214b3a8 100644 --- a/cps/search.py +++ b/cps/search.py @@ -22,7 +22,7 @@ from flask import session as flask_session from flask_login import current_user from flask_babel import format_date from flask_babel import gettext as _ -from sqlalchemy.sql.expression import func, not_, and_, or_, text +from sqlalchemy.sql.expression import func, not_, and_, or_, text, true from sqlalchemy.sql.functions import coalesce from . import logger, db, calibre_db, config, ub @@ -45,7 +45,7 @@ def simple_search(): return render_title_template('search.html', searchterm="", result_count=0, - title=_(u"Search"), + title=_("Search"), page="search") @@ -119,32 +119,26 @@ def adv_search_ratings(q, rating_high, rating_low): return q -def adv_search_read_status(q, read_status): - if read_status: - if config.config_read_column: - try: - if read_status == "True": - q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ - .filter(db.cc_classes[config.config_read_column].value == True) - else: - q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ - .filter(coalesce(db.cc_classes[config.config_read_column].value, False) != True) - except (KeyError, AttributeError): - log.error(u"Custom Column No.%d is not existing in calibre database", config.config_read_column) - flash(_("Custom Column No.%(column)d is not existing in calibre database", - column=config.config_read_column), - category="error") - return q +def adv_search_read_status(read_status): + if not config.config_read_column: + if read_status == "True": + db_filter = and_(ub.ReadBook.user_id == int(current_user.id), + ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) else: + db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED + else: + try: if read_status == "True": - q = q.join(ub.ReadBook, db.Books.id == ub.ReadBook.book_id, isouter=True) \ - .filter(ub.ReadBook.user_id == int(current_user.id), - ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) + db_filter = db.cc_classes[config.config_read_column].value == True else: - q = q.join(ub.ReadBook, db.Books.id == ub.ReadBook.book_id, isouter=True) \ - .filter(ub.ReadBook.user_id == int(current_user.id), - coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED) - return q + db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True + except (KeyError, AttributeError, IndexError): + log.error("Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) + flash(_("Custom Column No.%(column)d does not exist in calibre database", + column=config.config_read_column), + category="error") + return true() + return db_filter def adv_search_extension(q, include_extension_inputs, exclude_extension_inputs): @@ -191,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() @@ -220,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 @@ -238,23 +232,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True) calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase) - if not config.config_read_column: - query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(db.Books) - .outerjoin(ub.ReadBook, and_(db.Books.id == ub.ReadBook.book_id, - int(current_user.id) == ub.ReadBook.user_id))) - else: - try: - read_column = cc[config.config_read_column] - query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, read_column.value) - .select_from(db.Books) - .outerjoin(read_column, read_column.book == db.Books.id)) - except (KeyError, AttributeError): - log.error("Custom Column No.%d is not existing in calibre database", config.config_read_column) - # Skip linking read column - query = calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, None) - query = query.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id, - int(current_user.id) == ub.ArchivedBook.user_id)) - + query = calibre_db.generate_linked_query(config.config_read_column, db.Books) q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book)\ .outerjoin(db.Series)\ .filter(calibre_db.common_filters(True)) @@ -289,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, @@ -324,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 = adv_search_read_status(q, 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']) @@ -361,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]) @@ -388,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, @@ -411,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 0ffdbd18..30dad710 100644 --- a/cps/server.py +++ b/cps/server.py @@ -21,12 +21,13 @@ import os import errno import signal import socket -import subprocess # nosec +import asyncio try: - from gevent.pywsgi import WSGIServer + 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 +37,7 @@ except ImportError: from .tornado_wsgi import MyWSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop + from tornado import netutil from tornado import version as _version VERSION = 'Tornado ' + _version _GEVENT = False @@ -95,7 +97,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 +110,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 +165,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,17 +206,18 @@ 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, spawn=Pool(), **ssl_args) if ssl_args: wrap_socket = self.wsgiserver.wrap_socket @@ -225,17 +239,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)) - - # 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) + try: + # Max Buffersize set to 200MB + http_server = HTTPServer(MyWSGIContainer(self.app), + max_buffer_size=209700000, + ssl_options=self.ssl_args) + + 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 = netutil.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: @@ -261,9 +300,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() @@ -272,9 +318,14 @@ 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.asyncio_loop.call_soon_threadsafe(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 49d9a633..9d969322 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 @@ -71,6 +71,14 @@ def add_to_shelf(shelf_id, book_id): else: maxOrder = maxOrder[0] + if not calibre_db.session.query(db.Books).filter(db.Books.id == book_id).one_or_none(): + log.error("Invalid Book Id: %s. Could not be added to shelf %s", book_id, shelf.name) + if not xhr: + flash(_("%(book_id)s is a invalid Book Id. Could not be added to Shelf", book_id=book_id), + category="error") + return redirect(url_for('web.index')) + return "%s is a invalid Book Id. Could not be added to Shelf" % book_id, 400 + shelf.books.append(ub.BookShelf(shelf=shelf.id, book_id=book_id, order=maxOrder + 1)) shelf.last_modified = datetime.utcnow() try: @@ -79,14 +87,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 +108,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 +131,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 +143,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 +190,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 +205,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 +215,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 +223,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 +240,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')) @@ -263,13 +271,13 @@ def order_shelf(shelf_id): for book in books_in_shelf: setattr(book, 'order', to_save[str(book.book_id)]) counter += 1 - # if order diffrent from before -> shelf.last_modified = datetime.utcnow() + # if order different from before -> shelf.last_modified = datetime.utcnow() try: ub.session.commit() 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 +286,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 +303,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 +321,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 +338,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 +377,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 +388,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 +465,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/epub_themes.css b/cps/static/css/epub_themes.css new file mode 100644 index 00000000..16c27805 --- /dev/null +++ b/cps/static/css/epub_themes.css @@ -0,0 +1,19 @@ +.lightTheme { + background: #fff; + color: #000; +} + +.darkTheme { + background: #202124; + color: #fff +} + +.sepiaTheme { + background: #ece1ca; + color: #000; +} + +.blackTheme { + background: #000; + color: #fff +} \ No newline at end of file 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/libs/images/findbarButton-next-dark.svg b/cps/static/css/libs/images/findbarButton-next-dark.svg deleted file mode 100644 index 80df70bc..00000000 --- a/cps/static/css/libs/images/findbarButton-next-dark.svg +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/findbarButton-previous-dark.svg b/cps/static/css/libs/images/findbarButton-previous-dark.svg deleted file mode 100644 index d304a9b8..00000000 --- a/cps/static/css/libs/images/findbarButton-previous-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/grab.cur b/cps/static/css/libs/images/grab.cur deleted file mode 100644 index db7ad5ae..00000000 Binary files a/cps/static/css/libs/images/grab.cur and /dev/null differ diff --git a/cps/static/css/libs/images/grabbing.cur b/cps/static/css/libs/images/grabbing.cur deleted file mode 100644 index e0dfd04e..00000000 Binary files a/cps/static/css/libs/images/grabbing.cur and /dev/null differ diff --git a/cps/static/css/libs/images/secondaryToolbarButton-documentProperties-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-documentProperties-dark.svg deleted file mode 100644 index 306e628d..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-documentProperties-dark.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-firstPage-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-firstPage-dark.svg deleted file mode 100644 index c13ff867..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-firstPage-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-handTool-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-handTool-dark.svg deleted file mode 100644 index 834d8b0d..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-handTool-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-lastPage-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-lastPage-dark.svg deleted file mode 100644 index 8633e420..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-lastPage-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-rotateCcw-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-rotateCcw-dark.svg deleted file mode 100644 index 1a92f802..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-rotateCcw-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-rotateCw-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-rotateCw-dark.svg deleted file mode 100644 index 2a4ef738..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-rotateCw-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-scrollHorizontal-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-scrollHorizontal-dark.svg deleted file mode 100644 index 337f85ef..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-scrollHorizontal-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-scrollPage.svg b/cps/static/css/libs/images/secondaryToolbarButton-scrollPage.svg new file mode 100644 index 00000000..bea2f0d6 --- /dev/null +++ b/cps/static/css/libs/images/secondaryToolbarButton-scrollPage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-scrollVertical-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-scrollVertical-dark.svg deleted file mode 100644 index 41bdd8f1..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-scrollVertical-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-scrollWrapped-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-scrollWrapped-dark.svg deleted file mode 100644 index cd50526f..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-scrollWrapped-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-selectTool-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-selectTool-dark.svg deleted file mode 100644 index 7a95098a..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-selectTool-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-spreadEven-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-spreadEven-dark.svg deleted file mode 100644 index 0c9586ed..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-spreadEven-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-spreadNone-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-spreadNone-dark.svg deleted file mode 100644 index 75e1b985..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-spreadNone-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/secondaryToolbarButton-spreadOdd-dark.svg b/cps/static/css/libs/images/secondaryToolbarButton-spreadOdd-dark.svg deleted file mode 100644 index 8dff9598..00000000 --- a/cps/static/css/libs/images/secondaryToolbarButton-spreadOdd-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-bookmark-dark.svg b/cps/static/css/libs/images/toolbarButton-bookmark-dark.svg deleted file mode 100644 index 7bf33297..00000000 --- a/cps/static/css/libs/images/toolbarButton-bookmark-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-currentOutlineItem.svg b/cps/static/css/libs/images/toolbarButton-currentOutlineItem.svg new file mode 100644 index 00000000..c1c72b20 --- /dev/null +++ b/cps/static/css/libs/images/toolbarButton-currentOutlineItem.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-download-dark.svg b/cps/static/css/libs/images/toolbarButton-download-dark.svg deleted file mode 100644 index d2a92e5d..00000000 --- a/cps/static/css/libs/images/toolbarButton-download-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-editorFreeText.svg b/cps/static/css/libs/images/toolbarButton-editorFreeText.svg new file mode 100644 index 00000000..f0f11b47 --- /dev/null +++ b/cps/static/css/libs/images/toolbarButton-editorFreeText.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + diff --git a/cps/static/css/libs/images/toolbarButton-editorInk.svg b/cps/static/css/libs/images/toolbarButton-editorInk.svg new file mode 100644 index 00000000..2b37e85f --- /dev/null +++ b/cps/static/css/libs/images/toolbarButton-editorInk.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/cps/static/css/libs/images/toolbarButton-menuArrow-dark.svg b/cps/static/css/libs/images/toolbarButton-menuArrow-dark.svg deleted file mode 100644 index eb7f50e6..00000000 --- a/cps/static/css/libs/images/toolbarButton-menuArrow-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-openFile-dark.svg b/cps/static/css/libs/images/toolbarButton-openFile-dark.svg deleted file mode 100644 index 0bd612f0..00000000 --- a/cps/static/css/libs/images/toolbarButton-openFile-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-pageDown-dark.svg b/cps/static/css/libs/images/toolbarButton-pageDown-dark.svg deleted file mode 100644 index c2ca60c8..00000000 --- a/cps/static/css/libs/images/toolbarButton-pageDown-dark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-pageUp-dark.svg b/cps/static/css/libs/images/toolbarButton-pageUp-dark.svg deleted file mode 100644 index dddc4ab2..00000000 --- a/cps/static/css/libs/images/toolbarButton-pageUp-dark.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-presentationMode-dark.svg b/cps/static/css/libs/images/toolbarButton-presentationMode-dark.svg deleted file mode 100644 index 13fa9dc7..00000000 --- a/cps/static/css/libs/images/toolbarButton-presentationMode-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-print-dark.svg b/cps/static/css/libs/images/toolbarButton-print-dark.svg deleted file mode 100644 index ad37022f..00000000 --- a/cps/static/css/libs/images/toolbarButton-print-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-search-dark.svg b/cps/static/css/libs/images/toolbarButton-search-dark.svg deleted file mode 100644 index cec8a420..00000000 --- a/cps/static/css/libs/images/toolbarButton-search-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-secondaryToolbarToggle-dark.svg b/cps/static/css/libs/images/toolbarButton-secondaryToolbarToggle-dark.svg deleted file mode 100644 index 0160c07c..00000000 --- a/cps/static/css/libs/images/toolbarButton-secondaryToolbarToggle-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-sidebarToggle-dark.svg b/cps/static/css/libs/images/toolbarButton-sidebarToggle-dark.svg deleted file mode 100644 index 0118e41a..00000000 --- a/cps/static/css/libs/images/toolbarButton-sidebarToggle-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-viewAttachments-dark.svg b/cps/static/css/libs/images/toolbarButton-viewAttachments-dark.svg deleted file mode 100644 index c9714fde..00000000 --- a/cps/static/css/libs/images/toolbarButton-viewAttachments-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-viewLayers-dark.svg b/cps/static/css/libs/images/toolbarButton-viewLayers-dark.svg deleted file mode 100644 index 76b042a9..00000000 --- a/cps/static/css/libs/images/toolbarButton-viewLayers-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-viewOutline-dark.svg b/cps/static/css/libs/images/toolbarButton-viewOutline-dark.svg deleted file mode 100644 index 1704d961..00000000 --- a/cps/static/css/libs/images/toolbarButton-viewOutline-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-viewThumbnail-dark.svg b/cps/static/css/libs/images/toolbarButton-viewThumbnail-dark.svg deleted file mode 100644 index 17c55f7b..00000000 --- a/cps/static/css/libs/images/toolbarButton-viewThumbnail-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-zoomIn-dark.svg b/cps/static/css/libs/images/toolbarButton-zoomIn-dark.svg deleted file mode 100644 index 9b615541..00000000 --- a/cps/static/css/libs/images/toolbarButton-zoomIn-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/toolbarButton-zoomOut-dark.svg b/cps/static/css/libs/images/toolbarButton-zoomOut-dark.svg deleted file mode 100644 index 0fb3594d..00000000 --- a/cps/static/css/libs/images/toolbarButton-zoomOut-dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/cps/static/css/libs/images/treeitem-collapsed-dark.svg b/cps/static/css/libs/images/treeitem-collapsed-dark.svg deleted file mode 100644 index 1fb65516..00000000 --- a/cps/static/css/libs/images/treeitem-collapsed-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/images/treeitem-expanded-dark.svg b/cps/static/css/libs/images/treeitem-expanded-dark.svg deleted file mode 100644 index 695b0aa6..00000000 --- a/cps/static/css/libs/images/treeitem-expanded-dark.svg +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/cps/static/css/libs/viewer.css b/cps/static/css/libs/viewer.css index cd4781bf..c357a9fd 100644 --- a/cps/static/css/libs/viewer.css +++ b/cps/static/css/libs/viewer.css @@ -15,6 +15,7 @@ .textLayer { position: absolute; + text-align: initial; left: 0; top: 0; right: 0; @@ -22,9 +23,14 @@ overflow: hidden; opacity: 0.2; line-height: 1; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + text-size-adjust: none; + forced-color-adjust: none; } -.textLayer > span { +.textLayer span, +.textLayer br { color: transparent; position: absolute; white-space: pre; @@ -32,6 +38,13 @@ transform-origin: 0% 0%; } +/* Only necessary in Google Chrome, see issue 14205, and most unfortunately + * the problem doesn't show up in "text" reference tests. */ +.textLayer span.markedContent { + top: 0; + height: 0; +} + .textLayer .highlight { margin: -1px; padding: 1px; @@ -39,16 +52,20 @@ border-radius: 4px; } +.textLayer .highlight.appended { + position: initial; +} + .textLayer .highlight.begin { - border-radius: 4px 0px 0px 4px; + border-radius: 4px 0 0 4px; } .textLayer .highlight.end { - border-radius: 0px 4px 4px 0px; + border-radius: 0 4px 4px 0; } .textLayer .highlight.middle { - border-radius: 0px; + border-radius: 0; } .textLayer .highlight.selected { @@ -63,28 +80,61 @@ background: rgba(0, 0, 255, 1); } +/* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */ +.textLayer br::-moz-selection { + background: transparent; +} +.textLayer br::selection { + background: transparent; +} + .textLayer .endOfContent { display: block; position: absolute; - left: 0px; + left: 0; top: 100%; - right: 0px; - bottom: 0px; + right: 0; + bottom: 0; z-index: -1; cursor: default; -webkit-user-select: none; -moz-user-select: none; - -ms-user-select: none; user-select: none; } .textLayer .endOfContent.active { - top: 0px; + top: 0; +} + + +:root { + --annotation-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,"); +} + +@media (forced-colors: active) { + .annotationLayer .textWidgetAnnotation input:required, + .annotationLayer .textWidgetAnnotation textarea:required, + .annotationLayer .choiceWidgetAnnotation select:required, + .annotationLayer .buttonWidgetAnnotation.checkBox input:required, + .annotationLayer .buttonWidgetAnnotation.radioButton input:required { + outline: 1.5px solid selectedItem; + } } +.annotationLayer { + position: absolute; + top: 0; + left: 0; + pointer-events: none; + transform-origin: 0 0; +} .annotationLayer section { position: absolute; + text-align: initial; + pointer-events: auto; + box-sizing: border-box; + transform-origin: 0 0; } .annotationLayer .linkAnnotation > a, @@ -97,16 +147,23 @@ height: 100%; } +.annotationLayer .buttonWidgetAnnotation.pushButton > canvas { + width: 100%; + height: 100%; +} + .annotationLayer .linkAnnotation > a:hover, .annotationLayer .buttonWidgetAnnotation.pushButton > a:hover { opacity: 0.2; background: rgba(255, 255, 0, 1); - box-shadow: 0px 2px 10px rgba(255, 255, 0, 1); + box-shadow: 0 2px 10px rgba(255, 255, 0, 1); } .annotationLayer .textAnnotation img { position: absolute; cursor: pointer; + width: 100%; + height: 100%; } .annotationLayer .textWidgetAnnotation input, @@ -114,17 +171,24 @@ .annotationLayer .choiceWidgetAnnotation select, .annotationLayer .buttonWidgetAnnotation.checkBox input, .annotationLayer .buttonWidgetAnnotation.radioButton input { - background-color: rgba(0, 54, 255, 0.13); + background-image: var(--annotation-unfocused-field-background); border: 1px solid transparent; box-sizing: border-box; - font-size: 9px; + font: calc(9px * var(--scale-factor)) sans-serif; height: 100%; margin: 0; - padding: 0 3px; vertical-align: top; width: 100%; } +.annotationLayer .textWidgetAnnotation input:required, +.annotationLayer .textWidgetAnnotation textarea:required, +.annotationLayer .choiceWidgetAnnotation select:required, +.annotationLayer .buttonWidgetAnnotation.checkBox input:required, +.annotationLayer .buttonWidgetAnnotation.radioButton input:required { + outline: 1.5px solid red; +} + .annotationLayer .choiceWidgetAnnotation select option { padding: 0; } @@ -134,8 +198,6 @@ } .annotationLayer .textWidgetAnnotation textarea { - font: message-box; - font-size: 9px; resize: none; } @@ -164,10 +226,20 @@ border: 1px solid transparent; } +.annotationLayer .textWidgetAnnotation input :focus, +.annotationLayer .textWidgetAnnotation textarea :focus, +.annotationLayer .choiceWidgetAnnotation select :focus, +.annotationLayer .buttonWidgetAnnotation.checkBox :focus, +.annotationLayer .buttonWidgetAnnotation.radioButton :focus { + background-image: none; + background-color: transparent; + outline: auto; +} + .annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before, .annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after, .annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before { - background-color: rgba(0, 0, 0, 1); + background-color: CanvasText; content: ""; display: block; position: absolute; @@ -209,7 +281,7 @@ * area, causing horizontal scrolling. We avoid this by extending the width * when the element has focus and revert this when it loses focus. */ - width: 115%; + width: 103%; } .annotationLayer .buttonWidgetAnnotation.checkBox input, @@ -217,46 +289,59 @@ -webkit-appearance: none; -moz-appearance: none; appearance: none; - padding: 0; +} + +.annotationLayer .popupTriggerArea { + height: 100%; + width: 100%; } .annotationLayer .popupWrapper { position: absolute; - width: 20em; + font-size: calc(9px * var(--scale-factor)); + width: 100%; + min-width: calc(180px * var(--scale-factor)); + pointer-events: none; } .annotationLayer .popup { position: absolute; - z-index: 200; - max-width: 20em; + max-width: calc(180px * var(--scale-factor)); background-color: rgba(255, 255, 153, 1); - box-shadow: 0px 2px 5px rgba(136, 136, 136, 1); - border-radius: 2px; - padding: 6px; - margin-left: 5px; + box-shadow: 0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) + rgba(136, 136, 136, 1); + border-radius: calc(2px * var(--scale-factor)); + padding: calc(6px * var(--scale-factor)); + margin-left: calc(5px * var(--scale-factor)); cursor: pointer; font: message-box; - font-size: 9px; + white-space: normal; word-wrap: break-word; + pointer-events: auto; } .annotationLayer .popup > * { - font-size: 9px; + font-size: calc(9px * var(--scale-factor)); } .annotationLayer .popup h1 { display: inline-block; } -.annotationLayer .popup span { +.annotationLayer .popupDate { display: inline-block; - margin-left: 5px; + margin-left: calc(5px * var(--scale-factor)); } -.annotationLayer .popup p { +.annotationLayer .popupContent { border-top: 1px solid rgba(51, 51, 51, 1); - margin-top: 2px; - padding-top: 2px; + margin-top: calc(2px * var(--scale-factor)); + padding-top: calc(2px * var(--scale-factor)); +} + +.annotationLayer .richText > * { + white-space: pre-wrap; + font-size: calc(9px * var(--scale-factor)); } .annotationLayer .highlightAnnotation, @@ -276,2517 +361,1942 @@ cursor: pointer; } -.pdfViewer .canvasWrapper { - overflow: hidden; +.annotationLayer section svg { + position: absolute; + width: 100%; + height: 100%; } -.pdfViewer .page { - direction: ltr; - width: 816px; - height: 1056px; - margin: 1px auto -8px auto; - position: relative; - overflow: visible; - border: 9px solid transparent; - background-clip: content-box; - -o-border-image: url(images/shadow.png) 9 9 repeat; - border-image: url(images/shadow.png) 9 9 repeat; - background-color: rgba(255, 255, 255, 1); +.annotationLayer .annotationTextContent { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + color: transparent; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + pointer-events: none; } -.pdfViewer.removePageBorders .page { - margin: 0px auto 10px auto; - border: none; +.annotationLayer .annotationTextContent span { + width: 100%; + display: inline-block; } -.pdfViewer.singlePageView { - display: inline-block; + +:root { + --xfa-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,"); } -.pdfViewer.singlePageView .page { - margin: 0; - border: none; +@media (forced-colors: active) { + .xfaLayer *:required { + outline: 1.5px solid selectedItem; + } } -.pdfViewer.scrollHorizontal, -.pdfViewer.scrollWrapped, -.spread { - margin-left: 3.5px; - margin-right: 3.5px; - text-align: center; +.xfaLayer .highlight { + margin: -1px; + padding: 1px; + background-color: rgba(239, 203, 237, 1); + border-radius: 4px; } -.pdfViewer.scrollHorizontal, -.spread { - white-space: nowrap; +.xfaLayer .highlight.appended { + position: initial; } -.pdfViewer.removePageBorders, -.pdfViewer.scrollHorizontal .spread, -.pdfViewer.scrollWrapped .spread { - margin-left: 0; - margin-right: 0; +.xfaLayer .highlight.begin { + border-radius: 4px 0 0 4px; } -.spread .page, -.pdfViewer.scrollHorizontal .page, -.pdfViewer.scrollWrapped .page, -.pdfViewer.scrollHorizontal .spread, -.pdfViewer.scrollWrapped .spread { - display: inline-block; - vertical-align: middle; +.xfaLayer .highlight.end { + border-radius: 0 4px 4px 0; } -.spread .page, -.pdfViewer.scrollHorizontal .page, -.pdfViewer.scrollWrapped .page { - margin-left: -3.5px; - margin-right: -3.5px; +.xfaLayer .highlight.middle { + border-radius: 0; } -.pdfViewer.removePageBorders .spread .page, -.pdfViewer.removePageBorders.scrollHorizontal .page, -.pdfViewer.removePageBorders.scrollWrapped .page { - margin-left: 5px; - margin-right: 5px; +.xfaLayer .highlight.selected { + background-color: rgba(203, 223, 203, 1); } -.pdfViewer .page canvas { - margin: 0; - display: block; +.xfaLayer ::-moz-selection { + background: rgba(0, 0, 255, 1); } -.pdfViewer .page canvas[hidden] { +.xfaLayer ::selection { + background: rgba(0, 0, 255, 1); +} + +.xfaPage { + overflow: hidden; + position: relative; +} + +.xfaContentarea { + position: absolute; +} + +.xfaPrintOnly { display: none; } -.pdfViewer .page .loadingIcon { +.xfaLayer { position: absolute; - display: block; - left: 0; + text-align: initial; top: 0; - right: 0; - bottom: 0; - background: url("images/loading-icon.gif") center no-repeat; + left: 0; + transform-origin: 0 0; + line-height: 1.2; +} + +.xfaLayer * { + color: inherit; + font: inherit; + font-style: inherit; + font-weight: inherit; + font-kerning: inherit; + letter-spacing: -0.01px; + text-align: inherit; + text-decoration: inherit; + box-sizing: border-box; + background-color: transparent; + padding: 0; + margin: 0; + pointer-events: auto; + line-height: inherit; } -.pdfPresentationMode .pdfViewer { - margin-left: 0; - margin-right: 0; +.xfaLayer *:required { + outline: 1.5px solid red; } -.pdfPresentationMode .pdfViewer .page, -.pdfPresentationMode .pdfViewer .spread { - display: block; +.xfaLayer div { + pointer-events: none; } -.pdfPresentationMode .pdfViewer .page, -.pdfPresentationMode .pdfViewer.removePageBorders .page { - margin-left: auto; - margin-right: auto; +.xfaLayer svg { + pointer-events: none; } -.pdfPresentationMode:-ms-fullscreen .pdfViewer .page { - margin-bottom: 100% !important; +.xfaLayer svg * { + pointer-events: none; } -.pdfPresentationMode:-webkit-full-screen .pdfViewer .page { - margin-bottom: 100%; - border: 0; +.xfaLayer a { + color: blue; } -.pdfPresentationMode:-moz-full-screen .pdfViewer .page { - margin-bottom: 100%; - border: 0; +.xfaRich li { + margin-left: 3em; } -.pdfPresentationMode:fullscreen .pdfViewer .page { - margin-bottom: 100%; - border: 0; +.xfaFont { + color: black; + font-weight: normal; + font-kerning: none; + font-size: 10px; + font-style: normal; + letter-spacing: 0; + text-decoration: none; + vertical-align: 0; } -:root { - --sidebar-width: 200px; - --sidebar-transition-duration: 200ms; - --sidebar-transition-timing-function: ease; - - --toolbar-icon-opacity: 0.7; - --doorhanger-icon-opacity: 0.9; +.xfaCaption { + overflow: hidden; + flex: 0 0 auto; +} - --main-color: rgba(12, 12, 13, 1); - --body-bg-color: rgba(237, 237, 240, 1); - --errorWrapper-bg-color: rgba(255, 74, 74, 1); - --progressBar-color: rgba(10, 132, 255, 1); - --progressBar-indeterminate-bg-color: rgba(221, 221, 222, 1); - --progressBar-indeterminate-blend-color: rgba(116, 177, 239, 1); - --scrollbar-color: auto; - --scrollbar-bg-color: auto; +.xfaCaptionForCheckButton { + overflow: hidden; + flex: 1 1 auto; +} - --sidebar-bg-color: rgba(245, 246, 247, 1); - --toolbar-bg-color: rgba(249, 249, 250, 1); - --toolbar-border-color: rgba(204, 204, 204, 1); - --button-hover-color: rgba(221, 222, 223, 1); - --toggled-btn-bg-color: rgba(0, 0, 0, 0.3); - --dropdown-btn-bg-color: rgba(215, 215, 219, 1); - --separator-color: rgba(0, 0, 0, 0.3); - --field-color: rgba(6, 6, 6, 1); - --field-bg-color: rgba(255, 255, 255, 1); - --field-border-color: rgba(187, 187, 188, 1); - --findbar-nextprevious-btn-bg-color: rgba(227, 228, 230, 1); - --outline-color: rgba(0, 0, 0, 0.8); - --outline-hover-color: rgba(0, 0, 0, 0.9); - --outline-active-color: rgba(0, 0, 0, 0.08); - --outline-active-bg-color: rgba(0, 0, 0, 1); - --sidebaritem-bg-color: rgba(0, 0, 0, 0.15); - --doorhanger-bg-color: rgba(255, 255, 255, 1); - --doorhanger-border-color: rgba(12, 12, 13, 0.2); - --doorhanger-hover-color: rgba(237, 237, 237, 1); - --doorhanger-separator-color: rgba(222, 222, 222, 1); - --overlay-button-bg-color: rgba(12, 12, 13, 0.1); - --overlay-button-hover-color: rgba(12, 12, 13, 0.3); +.xfaLabel { + height: 100%; + width: 100%; +} - /*--loading-icon: url(images/loading.svg); - --treeitem-expanded-icon: url(images/treeitem-expanded.svg); - --treeitem-collapsed-icon: url(images/treeitem-collapsed.svg); - --toolbarButton-menuArrow-icon: url(images/toolbarButton-menuArrow.svg); - --toolbarButton-sidebarToggle-icon: url(images/toolbarButton-sidebarToggle.svg); - --toolbarButton-secondaryToolbarToggle-icon: url(images/toolbarButton-secondaryToolbarToggle.svg); - --toolbarButton-pageUp-icon: url(images/toolbarButton-pageUp.svg); - --toolbarButton-pageDown-icon: url(images/toolbarButton-pageDown.svg); - --toolbarButton-zoomOut-icon: url(images/toolbarButton-zoomOut.svg); - --toolbarButton-zoomIn-icon: url(images/toolbarButton-zoomIn.svg); - --toolbarButton-presentationMode-icon: url(images/toolbarButton-presentationMode.svg); - --toolbarButton-print-icon: url(images/toolbarButton-print.svg); - --toolbarButton-openFile-icon: url(images/toolbarButton-openFile.svg); - --toolbarButton-download-icon: url(images/toolbarButton-download.svg); - --toolbarButton-bookmark-icon: url(images/toolbarButton-bookmark.svg); - --toolbarButton-viewThumbnail-icon: url(images/toolbarButton-viewThumbnail.svg); - --toolbarButton-viewOutline-icon: url(images/toolbarButton-viewOutline.svg); - --toolbarButton-viewAttachments-icon: url(images/toolbarButton-viewAttachments.svg); - --toolbarButton-viewLayers-icon: url(images/toolbarButton-viewLayers.svg); - --toolbarButton-search-icon: url(images/toolbarButton-search.svg); - --findbarButton-previous-icon: url(images/findbarButton-previous.svg); - --findbarButton-next-icon: url(images/findbarButton-next.svg); - --secondaryToolbarButton-firstPage-icon: url(images/secondaryToolbarButton-firstPage.svg); - --secondaryToolbarButton-lastPage-icon: url(images/secondaryToolbarButton-lastPage.svg); - --secondaryToolbarButton-rotateCcw-icon: url(images/secondaryToolbarButton-rotateCcw.svg); - --secondaryToolbarButton-rotateCw-icon: url(images/secondaryToolbarButton-rotateCw.svg); - --secondaryToolbarButton-selectTool-icon: url(images/secondaryToolbarButton-selectTool.svg); - --secondaryToolbarButton-handTool-icon: url(images/secondaryToolbarButton-handTool.svg); - --secondaryToolbarButton-scrollVertical-icon: url(images/secondaryToolbarButton-scrollVertical.svg); - --secondaryToolbarButton-scrollHorizontal-icon: url(images/secondaryToolbarButton-scrollHorizontal.svg); - --secondaryToolbarButton-scrollWrapped-icon: url(images/secondaryToolbarButton-scrollWrapped.svg); - --secondaryToolbarButton-spreadNone-icon: url(images/secondaryToolbarButton-spreadNone.svg); - --secondaryToolbarButton-spreadOdd-icon: url(images/secondaryToolbarButton-spreadOdd.svg); - --secondaryToolbarButton-spreadEven-icon: url(images/secondaryToolbarButton-spreadEven.svg); - --secondaryToolbarButton-documentProperties-icon: url(images/secondaryToolbarButton-documentProperties.svg);*/ +.xfaLeft { + display: flex; + flex-direction: row; + align-items: center; } -@media (prefers-color-scheme: dark) { - :root { - --main-color: rgba(249, 249, 250, 1); - --body-bg-color: rgba(42, 42, 46, 1); - --errorWrapper-bg-color: rgba(199, 17, 17, 1); - --progressBar-color: rgba(0, 96, 223, 1); - --progressBar-indeterminate-bg-color: rgba(40, 40, 43, 1); - --progressBar-indeterminate-blend-color: rgba(20, 68, 133, 1); - --scrollbar-color: rgba(121, 121, 123, 1); - --scrollbar-bg-color: rgba(35, 35, 39, 1); +.xfaRight { + display: flex; + flex-direction: row-reverse; + align-items: center; +} - --sidebar-bg-color: rgba(50, 50, 52, 1); - --toolbar-bg-color: rgba(56, 56, 61, 1); - --toolbar-border-color: rgba(12, 12, 13, 1); - --button-hover-color: rgba(102, 102, 103, 1); - --toggled-btn-bg-color: rgba(0, 0, 0, 0.3); - --dropdown-btn-bg-color: rgba(74, 74, 79, 1); - --separator-color: rgba(0, 0, 0, 0.3); - --field-color: rgba(250, 250, 250, 1); - --field-bg-color: rgba(64, 64, 68, 1); - --field-border-color: rgba(115, 115, 115, 1); - --findbar-nextprevious-btn-bg-color: rgba(89, 89, 89, 1); - --outline-color: rgba(255, 255, 255, 0.8); - --outline-hover-color: rgba(255, 255, 255, 0.9); - --outline-active-color: rgba(255, 255, 255, 0.08); - --outline-active-bg-color: rgba(255, 255, 255, 1); - --sidebaritem-bg-color: rgba(255, 255, 255, 0.15); - --doorhanger-bg-color: rgba(74, 74, 79, 1); - --doorhanger-border-color: rgba(39, 39, 43, 1); - --doorhanger-hover-color: rgba(93, 94, 98, 1); - --doorhanger-separator-color: rgba(92, 92, 97, 1); - --overlay-button-bg-color: rgba(92, 92, 97, 1); - --overlay-button-hover-color: rgba(115, 115, 115, 1); - } +.xfaLeft > .xfaCaption, +.xfaLeft > .xfaCaptionForCheckButton, +.xfaRight > .xfaCaption, +.xfaRight > .xfaCaptionForCheckButton { + max-height: 100%; } -* { - padding: 0; - margin: 0; +.xfaTop { + display: flex; + flex-direction: column; + align-items: flex-start; } -html { - height: 100%; - width: 100%; - /* Font size is needed to make the activity bar the correct size. */ - font-size: 10px; +.xfaBottom { + display: flex; + flex-direction: column-reverse; + align-items: flex-start; } -body { - height: 100%; +.xfaTop > .xfaCaption, +.xfaTop > .xfaCaptionForCheckButton, +.xfaBottom > .xfaCaption, +.xfaBottom > .xfaCaptionForCheckButton { width: 100%; - background-color: rgba(237, 237, 240, 1); - background-color: var(--body-bg-color); } -@media (prefers-color-scheme: dark) { - - body { - background-color: rgba(42, 42, 46, 1); - background-color: var(--body-bg-color); - } +.xfaBorder { + background-color: transparent; + position: absolute; + pointer-events: none; } -body { - font: message-box; - outline: none; - scrollbar-color: auto auto; - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); +.xfaWrapped { + width: 100%; + height: 100%; } -@media (prefers-color-scheme: dark) { - - body { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaTextfield:focus, +.xfaSelect:focus { + background-image: none; + background-color: transparent; + outline: auto; + outline-offset: -1px; } -@media (prefers-color-scheme: dark) { - - body { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaCheckbox:focus, +.xfaRadio:focus { + outline: auto; } -@media (prefers-color-scheme: dark) { - - body { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaTextfield, +.xfaSelect { + height: 100%; + width: 100%; + flex: 1 1 auto; + border: none; + resize: none; + background-image: var(--xfa-unfocused-field-background); } -@media (prefers-color-scheme: dark) { - - body { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaTop > .xfaTextfield, +.xfaTop > .xfaSelect, +.xfaBottom > .xfaTextfield, +.xfaBottom > .xfaSelect { + flex: 0 1 auto; } -input { - font: message-box; - outline: none; - scrollbar-color: auto auto; - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); +.xfaButton { + cursor: pointer; + width: 100%; + height: 100%; + border: none; + text-align: center; } -@media (prefers-color-scheme: dark) { - - input { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaLink { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; } -@media (prefers-color-scheme: dark) { - - input { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaCheckbox, +.xfaRadio { + width: 100%; + height: 100%; + flex: 0 0 auto; + border: none; } -@media (prefers-color-scheme: dark) { - - input { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaRich { + white-space: pre-wrap; + width: 100%; + height: 100%; } -@media (prefers-color-scheme: dark) { - - input { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaImage { + -o-object-position: left top; + object-position: left top; + -o-object-fit: contain; + object-fit: contain; + width: 100%; + height: 100%; } -button { - font: message-box; - outline: none; - scrollbar-color: auto auto; - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); +.xfaLrTb, +.xfaRlTb, +.xfaTb { + display: flex; + flex-direction: column; + align-items: stretch; } -@media (prefers-color-scheme: dark) { +.xfaLr { + display: flex; + flex-direction: row; + align-items: stretch; +} - button { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaRl { + display: flex; + flex-direction: row-reverse; + align-items: stretch; } -@media (prefers-color-scheme: dark) { +.xfaTb > div { + justify-content: left; +} - button { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaPosition { + position: relative; } -@media (prefers-color-scheme: dark) { +.xfaArea { + position: relative; +} - button { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaValignMiddle { + display: flex; + align-items: center; } -@media (prefers-color-scheme: dark) { +.xfaTable { + display: flex; + flex-direction: column; + align-items: stretch; +} - button { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaTable .xfaRow { + display: flex; + flex-direction: row; + align-items: stretch; } -select { - font: message-box; - outline: none; - scrollbar-color: auto auto; - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); +.xfaTable .xfaRlRow { + display: flex; + flex-direction: row-reverse; + align-items: stretch; + flex: 1; } -@media (prefers-color-scheme: dark) { +.xfaTable .xfaRlRow > div { + flex: 1; +} - select { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +.xfaNonInteractive input, +.xfaNonInteractive textarea, +.xfaDisabled input, +.xfaDisabled textarea, +.xfaReadOnly input, +.xfaReadOnly textarea { + background: initial; } -@media (prefers-color-scheme: dark) { +@media print { + .xfaTextfield, + .xfaSelect { + background: transparent; + } - select { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); + .xfaSelect { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + text-indent: 1px; + text-overflow: ""; } } -@media (prefers-color-scheme: dark) { - select { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); - } +:root { + --focus-outline: solid 2px blue; + --hover-outline: dashed 2px blue; + --freetext-line-height: 1.35; + --freetext-padding: 2px; + --editorInk-editing-cursor: url(images/toolbarButton-editorInk.svg) 0 16; } -@media (prefers-color-scheme: dark) { - - select { - scrollbar-color: rgba(121, 121, 123, 1) rgba(35, 35, 39, 1); - scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); +@media (forced-colors: active) { + :root { + --focus-outline: solid 3px ButtonText; + --hover-outline: dashed 3px ButtonText; } } -.hidden { - display: none !important; +[data-editor-rotation="90"] { + transform: rotate(90deg); } -[hidden] { - display: none !important; +[data-editor-rotation="180"] { + transform: rotate(180deg); } - -.pdfViewer.enablePermissions .textLayer > span { - -webkit-user-select: none !important; - -moz-user-select: none !important; - -ms-user-select: none !important; - user-select: none !important; - cursor: not-allowed; +[data-editor-rotation="270"] { + transform: rotate(270deg); } -#viewerContainer.pdfPresentationMode:-ms-fullscreen { - top: 0px !important; - overflow: hidden !important; +.annotationEditorLayer { + background: transparent; + position: absolute; + top: 0; + left: 0; + font-size: calc(100px * var(--scale-factor)); + transform-origin: 0 0; } -#viewerContainer.pdfPresentationMode:-ms-fullscreen::-ms-backdrop { - background-color: rgba(0, 0, 0, 1); +.annotationEditorLayer .selectedEditor { + outline: var(--focus-outline); + resize: none; } -#viewerContainer.pdfPresentationMode:-webkit-full-screen { - top: 0px; - border-top: 2px solid rgba(0, 0, 0, 0); - background-color: rgba(0, 0, 0, 1); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; - -webkit-user-select: none; - user-select: none; +.annotationEditorLayer .freeTextEditor { + position: absolute; + background: transparent; + border-radius: 3px; + padding: calc(var(--freetext-padding) * var(--scale-factor)); + resize: none; + width: auto; + height: auto; + z-index: 1; + transform-origin: 0 0; + touch-action: none; } -#viewerContainer.pdfPresentationMode:-moz-full-screen { - top: 0px; - border-top: 2px solid rgba(0, 0, 0, 0); - background-color: rgba(0, 0, 0, 1); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; - -moz-user-select: none; - user-select: none; +.annotationEditorLayer .freeTextEditor .internal { + background: transparent; + border: none; + top: 0; + left: 0; + overflow: visible; + white-space: nowrap; + resize: none; + font: 10px sans-serif; + line-height: var(--freetext-line-height); } -#viewerContainer.pdfPresentationMode:-ms-fullscreen { - top: 0px; - border-top: 2px solid rgba(0, 0, 0, 0); - background-color: rgba(0, 0, 0, 1); +.annotationEditorLayer .freeTextEditor .overlay { + position: absolute; + display: none; + background: transparent; + top: 0; + left: 0; width: 100%; height: 100%; - overflow: hidden; - cursor: none; - -ms-user-select: none; - user-select: none; } -#viewerContainer.pdfPresentationMode:fullscreen { - top: 0px; - border-top: 2px solid rgba(0, 0, 0, 0); - background-color: rgba(0, 0, 0, 1); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; +.annotationEditorLayer .freeTextEditor .overlay.enabled { + display: block; } -.pdfPresentationMode:-webkit-full-screen a:not(.internalLink) { - display: none; +.annotationEditorLayer .freeTextEditor .internal:empty::before { + content: attr(default-content); + color: gray; } -.pdfPresentationMode:-moz-full-screen a:not(.internalLink) { - display: none; +.annotationEditorLayer .freeTextEditor .internal:focus { + outline: none; } -.pdfPresentationMode:-ms-fullscreen a:not(.internalLink) { - display: none; +.annotationEditorLayer .inkEditor.disabled { + resize: none; } -.pdfPresentationMode:fullscreen a:not(.internalLink) { - display: none; +.annotationEditorLayer .inkEditor.disabled.selectedEditor { + resize: horizontal; } -.pdfPresentationMode:-webkit-full-screen .textLayer > span { - cursor: none; +.annotationEditorLayer .freeTextEditor:hover:not(.selectedEditor), +.annotationEditorLayer .inkEditor:hover:not(.selectedEditor) { + outline: var(--hover-outline); } -.pdfPresentationMode:-moz-full-screen .textLayer > span { - cursor: none; +.annotationEditorLayer .inkEditor { + position: absolute; + background: transparent; + border-radius: 3px; + overflow: auto; + width: 100%; + height: 100%; + z-index: 1; + transform-origin: 0 0; + cursor: auto; } -.pdfPresentationMode:-ms-fullscreen .textLayer > span { - cursor: none; +.annotationEditorLayer .inkEditor.editing { + resize: none; + cursor: var(--editorInk-editing-cursor), pointer; } -.pdfPresentationMode:fullscreen .textLayer > span { - cursor: none; +.annotationEditorLayer .inkEditor .inkEditorCanvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + touch-action: none; } -.pdfPresentationMode.pdfPresentationModeControls > *, -.pdfPresentationMode.pdfPresentationModeControls .textLayer > span { - cursor: default; +:root { + --viewer-container-height: 0; + --pdfViewer-padding-bottom: 0; + --page-margin: 1px auto -8px; + --page-border: 9px solid transparent; + --page-border-image: url(images/shadow.png) 9 9 repeat; + --spreadHorizontalWrapped-margin-LR: -3.5px; + --scale-factor: 1; } -#outerContainer { - width: 100%; - height: 100%; - position: relative; +@media screen and (forced-colors: active) { + :root { + --pdfViewer-padding-bottom: 9px; + --page-margin: 8px auto -1px; + --page-border: 1px solid CanvasText; + --page-border-image: none; + --spreadHorizontalWrapped-margin-LR: 3.5px; + } } -#sidebarContainer { - position: absolute; - top: 32px; - bottom: 0; - width: 200px; - width: var(--sidebar-width); - visibility: hidden; - z-index: 100; - border-top: 1px solid rgba(51, 51, 51, 1); - transition-duration: 200ms; - transition-duration: var(--sidebar-transition-duration); - transition-timing-function: ease; - transition-timing-function: var(--sidebar-transition-timing-function); +[data-main-rotation="90"] { + transform: rotate(90deg) translateY(-100%); } -html[dir="ltr"] #sidebarContainer { - transition-property: left; - left: -200px; - left: calc(0px - var(--sidebar-width)); +[data-main-rotation="180"] { + transform: rotate(180deg) translate(-100%, -100%); } -html[dir="rtl"] #sidebarContainer { - transition-property: right; - right: -200px; - right: calc(0px - var(--sidebar-width)); +[data-main-rotation="270"] { + transform: rotate(270deg) translateX(-100%); } -.loadingInProgress #sidebarContainer { - top: 36px; +.pdfViewer { + padding-bottom: var(--pdfViewer-padding-bottom); } -#outerContainer.sidebarResizing #sidebarContainer { - /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */ - transition-duration: 0s; - /* Prevent e.g. the thumbnails being selected when the sidebar is resized. */ - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; +.pdfViewer .canvasWrapper { + overflow: hidden; } -#outerContainer.sidebarMoving #sidebarContainer, -#outerContainer.sidebarOpen #sidebarContainer { - visibility: visible; -} -html[dir="ltr"] #outerContainer.sidebarOpen #sidebarContainer { - left: 0px; -} -html[dir="rtl"] #outerContainer.sidebarOpen #sidebarContainer { - right: 0px; +.pdfViewer .page { + direction: ltr; + width: 816px; + height: 1056px; + margin: var(--page-margin); + position: relative; + overflow: visible; + border: var(--page-border); + -o-border-image: var(--page-border-image); + border-image: var(--page-border-image); + background-clip: content-box; + background-color: rgba(255, 255, 255, 1); } -#mainContainer { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - min-width: 320px; +.pdfViewer .dummyPage { + position: relative; + width: 0; + height: var(--viewer-container-height); } -#sidebarContent { - top: 32px; - bottom: 0; - overflow: auto; - -webkit-overflow-scrolling: touch; - position: absolute; - width: 100%; - background-color: rgba(0, 0, 0, 0.1); +.pdfViewer.removePageBorders .page { + margin: 0 auto 10px; + border: none; } -html[dir="ltr"] #sidebarContent { - left: 0; - box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25); + +.pdfViewer.singlePageView { + display: inline-block; } -html[dir="rtl"] #sidebarContent { - right: 0; - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.25); + +.pdfViewer.singlePageView .page { + margin: 0; + border: none; } -#viewerContainer { - overflow: auto; - -webkit-overflow-scrolling: touch; - position: absolute; - top: 32px; - right: 0; - bottom: 0; - left: 0; - outline: none; -} -#viewerContainer:not(.pdfPresentationMode) { - transition-duration: 200ms; - transition-duration: var(--sidebar-transition-duration); - transition-timing-function: ease; - transition-timing-function: var(--sidebar-transition-timing-function); +.pdfViewer.scrollHorizontal, +.pdfViewer.scrollWrapped, +.spread { + margin-left: 3.5px; + margin-right: 3.5px; + text-align: center; } -#outerContainer.sidebarResizing #viewerContainer { - /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */ - transition-duration: 0s; +.pdfViewer.scrollHorizontal, +.spread { + white-space: nowrap; } -html[dir="ltr"] - #outerContainer.sidebarOpen - #viewerContainer:not(.pdfPresentationMode) { - transition-property: left; - left: 200px; - left: var(--sidebar-width); -} -html[dir="rtl"] - #outerContainer.sidebarOpen - #viewerContainer:not(.pdfPresentationMode) { - transition-property: right; - right: 200px; - right: var(--sidebar-width); +.pdfViewer.removePageBorders, +.pdfViewer.scrollHorizontal .spread, +.pdfViewer.scrollWrapped .spread { + margin-left: 0; + margin-right: 0; } -.toolbar { - position: relative; - left: 0; - right: 0; - z-index: 9999; - cursor: default; +.spread .page, +.spread .dummyPage, +.pdfViewer.scrollHorizontal .page, +.pdfViewer.scrollWrapped .page, +.pdfViewer.scrollHorizontal .spread, +.pdfViewer.scrollWrapped .spread { + display: inline-block; + vertical-align: middle; } -#toolbarContainer { - width: 100%; +.spread .page, +.pdfViewer.scrollHorizontal .page, +.pdfViewer.scrollWrapped .page { + margin-left: var(--spreadHorizontalWrapped-margin-LR); + margin-right: var(--spreadHorizontalWrapped-margin-LR); } -#toolbarSidebar { - width: 100%; - height: 32px; - background-color: rgba(245, 246, 247, 1); - background-color: var(--sidebar-bg-color); +.pdfViewer.removePageBorders .spread .page, +.pdfViewer.removePageBorders.scrollHorizontal .page, +.pdfViewer.removePageBorders.scrollWrapped .page { + margin-left: 5px; + margin-right: 5px; } -@media (prefers-color-scheme: dark) { - - #toolbarSidebar { - background-color: rgba(50, 50, 52, 1); - background-color: var(--sidebar-bg-color); - } -} -html[dir="ltr"] #toolbarSidebar { - box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.15), - 0 0 1px rgba(0, 0, 0, 0.1); -} -html[dir="rtl"] #toolbarSidebar { - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.15), - 0 0 1px rgba(0, 0, 0, 0.1); +.pdfViewer .page canvas { + margin: 0; + display: block; } -html[dir="ltr"] #toolbarSidebar .toolbarButton { - margin-right: 2px !important; -} -html[dir="rtl"] #toolbarSidebar .toolbarButton { - margin-left: 2px !important; +.pdfViewer .page canvas[hidden] { + display: none; } -#sidebarResizer { +.pdfViewer .page .loadingIcon { position: absolute; + display: block; + left: 0; top: 0; + right: 0; bottom: 0; - width: 6px; - z-index: 200; - cursor: ew-resize; -} -html[dir="ltr"] #sidebarResizer { - right: -6px; + background: url("images/loading-icon.gif") center no-repeat; } -html[dir="rtl"] #sidebarResizer { - left: -6px; +.pdfViewer .page .loadingIcon.notVisible { + background: none; } -#toolbarContainer { - position: relative; - height: 32px; - background-color: rgba(249, 249, 250, 1); - background-color: var(--toolbar-bg-color); +.pdfViewer.enablePermissions .textLayer span { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important; + cursor: not-allowed; } -@media (prefers-color-scheme: dark) { +.pdfPresentationMode .pdfViewer { + padding-bottom: 0; +} - #toolbarContainer { - background-color: rgba(56, 56, 61, 1); - background-color: var(--toolbar-bg-color); - } +.pdfPresentationMode .spread { + margin: 0; } -.findbar { - position: relative; - height: 32px; - background-color: rgba(249, 249, 250, 1); - background-color: var(--toolbar-bg-color); +.pdfPresentationMode .pdfViewer .page { + margin: 0 auto; + border: 2px solid transparent; } -@media (prefers-color-scheme: dark) { +:root { + --dir-factor: 1; + --sidebar-width: 200px; + --sidebar-transition-duration: 200ms; + --sidebar-transition-timing-function: ease; + --scale-select-container-width: 140px; + --scale-select-overflow: 22px; - .findbar { - background-color: rgba(56, 56, 61, 1); - background-color: var(--toolbar-bg-color); - } -} + --toolbar-icon-opacity: 0.7; + --doorhanger-icon-opacity: 0.9; -.secondaryToolbar { - position: relative; - height: 32px; - background-color: rgba(249, 249, 250, 1); - background-color: var(--toolbar-bg-color); -} + --main-color: rgba(12, 12, 13, 1); + --body-bg-color: rgba(237, 237, 240, 1); + --errorWrapper-bg-color: rgba(255, 110, 110, 1); + --progressBar-percent: 0%; + --progressBar-end-offset: 0; + --progressBar-color: rgba(10, 132, 255, 1); + --progressBar-indeterminate-bg-color: rgba(221, 221, 222, 1); + --progressBar-indeterminate-blend-color: rgba(116, 177, 239, 1); + --scrollbar-color: auto; + --scrollbar-bg-color: auto; + --toolbar-icon-bg-color: rgba(0, 0, 0, 1); + --toolbar-icon-hover-bg-color: rgba(0, 0, 0, 1); -@media (prefers-color-scheme: dark) { + --sidebar-narrow-bg-color: rgba(237, 237, 240, 0.9); + --sidebar-toolbar-bg-color: rgba(245, 246, 247, 1); + --toolbar-bg-color: rgba(249, 249, 250, 1); + --toolbar-border-color: rgba(204, 204, 204, 1); + --button-hover-color: rgba(221, 222, 223, 1); + --toggled-btn-color: rgba(0, 0, 0, 1); + --toggled-btn-bg-color: rgba(0, 0, 0, 0.3); + --toggled-hover-active-btn-color: rgba(0, 0, 0, 0.4); + --dropdown-btn-bg-color: rgba(215, 215, 219, 1); + --separator-color: rgba(0, 0, 0, 0.3); + --field-color: rgba(6, 6, 6, 1); + --field-bg-color: rgba(255, 255, 255, 1); + --field-border-color: rgba(187, 187, 188, 1); + --treeitem-color: rgba(0, 0, 0, 0.8); + --treeitem-hover-color: rgba(0, 0, 0, 0.9); + --treeitem-selected-color: rgba(0, 0, 0, 0.9); + --treeitem-selected-bg-color: rgba(0, 0, 0, 0.25); + --sidebaritem-bg-color: rgba(0, 0, 0, 0.15); + --doorhanger-bg-color: rgba(255, 255, 255, 1); + --doorhanger-border-color: rgba(12, 12, 13, 0.2); + --doorhanger-hover-color: rgba(12, 12, 13, 1); + --doorhanger-hover-bg-color: rgba(237, 237, 237, 1); + --doorhanger-separator-color: rgba(222, 222, 222, 1); + --dialog-button-border: 0 none; + --dialog-button-bg-color: rgba(12, 12, 13, 0.1); + --dialog-button-hover-bg-color: rgba(12, 12, 13, 0.3); - .secondaryToolbar { - background-color: rgba(56, 56, 61, 1); - background-color: var(--toolbar-bg-color); - } -} -html[dir="ltr"] #toolbarContainer { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); + --loading-icon: url(images/loading.svg); + --treeitem-expanded-icon: url(images/treeitem-expanded.svg); + --treeitem-collapsed-icon: url(images/treeitem-collapsed.svg); + --toolbarButton-editorFreeText-icon: url(images/toolbarButton-editorFreeText.svg); + --toolbarButton-editorInk-icon: url(images/toolbarButton-editorInk.svg); + --toolbarButton-menuArrow-icon: url(images/toolbarButton-menuArrow.svg); + --toolbarButton-sidebarToggle-icon: url(images/toolbarButton-sidebarToggle.svg); + --toolbarButton-secondaryToolbarToggle-icon: url(images/toolbarButton-secondaryToolbarToggle.svg); + --toolbarButton-pageUp-icon: url(images/toolbarButton-pageUp.svg); + --toolbarButton-pageDown-icon: url(images/toolbarButton-pageDown.svg); + --toolbarButton-zoomOut-icon: url(images/toolbarButton-zoomOut.svg); + --toolbarButton-zoomIn-icon: url(images/toolbarButton-zoomIn.svg); + --toolbarButton-presentationMode-icon: url(images/toolbarButton-presentationMode.svg); + --toolbarButton-print-icon: url(images/toolbarButton-print.svg); + --toolbarButton-openFile-icon: url(images/toolbarButton-openFile.svg); + --toolbarButton-download-icon: url(images/toolbarButton-download.svg); + --toolbarButton-bookmark-icon: url(images/toolbarButton-bookmark.svg); + --toolbarButton-viewThumbnail-icon: url(images/toolbarButton-viewThumbnail.svg); + --toolbarButton-viewOutline-icon: url(images/toolbarButton-viewOutline.svg); + --toolbarButton-viewAttachments-icon: url(images/toolbarButton-viewAttachments.svg); + --toolbarButton-viewLayers-icon: url(images/toolbarButton-viewLayers.svg); + --toolbarButton-currentOutlineItem-icon: url(images/toolbarButton-currentOutlineItem.svg); + --toolbarButton-search-icon: url(images/toolbarButton-search.svg); + --findbarButton-previous-icon: url(images/findbarButton-previous.svg); + --findbarButton-next-icon: url(images/findbarButton-next.svg); + --secondaryToolbarButton-firstPage-icon: url(images/secondaryToolbarButton-firstPage.svg); + --secondaryToolbarButton-lastPage-icon: url(images/secondaryToolbarButton-lastPage.svg); + --secondaryToolbarButton-rotateCcw-icon: url(images/secondaryToolbarButton-rotateCcw.svg); + --secondaryToolbarButton-rotateCw-icon: url(images/secondaryToolbarButton-rotateCw.svg); + --secondaryToolbarButton-selectTool-icon: url(images/secondaryToolbarButton-selectTool.svg); + --secondaryToolbarButton-handTool-icon: url(images/secondaryToolbarButton-handTool.svg); + --secondaryToolbarButton-scrollPage-icon: url(images/secondaryToolbarButton-scrollPage.svg); + --secondaryToolbarButton-scrollVertical-icon: url(images/secondaryToolbarButton-scrollVertical.svg); + --secondaryToolbarButton-scrollHorizontal-icon: url(images/secondaryToolbarButton-scrollHorizontal.svg); + --secondaryToolbarButton-scrollWrapped-icon: url(images/secondaryToolbarButton-scrollWrapped.svg); + --secondaryToolbarButton-spreadNone-icon: url(images/secondaryToolbarButton-spreadNone.svg); + --secondaryToolbarButton-spreadOdd-icon: url(images/secondaryToolbarButton-spreadOdd.svg); + --secondaryToolbarButton-spreadEven-icon: url(images/secondaryToolbarButton-spreadEven.svg); + --secondaryToolbarButton-documentProperties-icon: url(images/secondaryToolbarButton-documentProperties.svg); } -@media (prefers-color-scheme: dark) { - html[dir="ltr"] #toolbarContainer { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); - } -} -.findbar { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); +[dir="rtl"]:root { + --dir-factor: -1; } -@media (prefers-color-scheme: dark) { - .findbar { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); - } -} -.secondaryToolbar { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); -} @media (prefers-color-scheme: dark) { + :root { + --main-color: rgba(249, 249, 250, 1); + --body-bg-color: rgba(42, 42, 46, 1); + --errorWrapper-bg-color: rgba(169, 14, 14, 1); + --progressBar-color: rgba(0, 96, 223, 1); + --progressBar-indeterminate-bg-color: rgba(40, 40, 43, 1); + --progressBar-indeterminate-blend-color: rgba(20, 68, 133, 1); + --scrollbar-color: rgba(121, 121, 123, 1); + --scrollbar-bg-color: rgba(35, 35, 39, 1); + --toolbar-icon-bg-color: rgba(255, 255, 255, 1); + --toolbar-icon-hover-bg-color: rgba(255, 255, 255, 1); - .secondaryToolbar { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); - } -} -html[dir="rtl"] #toolbarContainer { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); -} -@media (prefers-color-scheme: dark) { + --sidebar-narrow-bg-color: rgba(42, 42, 46, 0.9); + --sidebar-toolbar-bg-color: rgba(50, 50, 52, 1); + --toolbar-bg-color: rgba(56, 56, 61, 1); + --toolbar-border-color: rgba(12, 12, 13, 1); + --button-hover-color: rgba(102, 102, 103, 1); + --toggled-btn-color: rgba(255, 255, 255, 1); + --toggled-btn-bg-color: rgba(0, 0, 0, 0.3); + --toggled-hover-active-btn-color: rgba(0, 0, 0, 0.4); + --dropdown-btn-bg-color: rgba(74, 74, 79, 1); + --separator-color: rgba(0, 0, 0, 0.3); + --field-color: rgba(250, 250, 250, 1); + --field-bg-color: rgba(64, 64, 68, 1); + --field-border-color: rgba(115, 115, 115, 1); + --treeitem-color: rgba(255, 255, 255, 0.8); + --treeitem-hover-color: rgba(255, 255, 255, 0.9); + --treeitem-selected-color: rgba(255, 255, 255, 0.9); + --treeitem-selected-bg-color: rgba(255, 255, 255, 0.25); + --sidebaritem-bg-color: rgba(255, 255, 255, 0.15); + --doorhanger-bg-color: rgba(74, 74, 79, 1); + --doorhanger-border-color: rgba(39, 39, 43, 1); + --doorhanger-hover-color: rgba(249, 249, 250, 1); + --doorhanger-hover-bg-color: rgba(93, 94, 98, 1); + --doorhanger-separator-color: rgba(92, 92, 97, 1); + --dialog-button-bg-color: rgba(92, 92, 97, 1); + --dialog-button-hover-bg-color: rgba(115, 115, 115, 1); - html[dir="rtl"] #toolbarContainer { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); + /* This image is used in elements, which unfortunately means that + * the `mask-image` approach used with all of the other images doesn't work + * here; hence why we still have two versions of this particular image. */ + --loading-icon: url(images/loading-dark.svg); } } -.findbar { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); -} -@media (prefers-color-scheme: dark) { - .findbar { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); +@media screen and (forced-colors: active) { + :root { + --button-hover-color: Highlight; + --doorhanger-hover-bg-color: Highlight; + --toolbar-icon-opacity: 1; + --toolbar-icon-bg-color: ButtonText; + --toolbar-icon-hover-bg-color: ButtonFace; + --toggled-btn-color: HighlightText; + --toggled-btn-bg-color: LinkText; + --doorhanger-hover-color: ButtonFace; + --doorhanger-border-color-whcm: 1px solid ButtonText; + --doorhanger-triangle-opacity-whcm: 0; + --dialog-button-border: 1px solid Highlight; + --dialog-button-hover-bg-color: Highlight; + --dialog-button-hover-color: ButtonFace; + --field-border-color: ButtonText; } } -.secondaryToolbar { - box-shadow: 0 1px 0 rgba(204, 204, 204, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); -} -@media (prefers-color-scheme: dark) { - .secondaryToolbar { - box-shadow: 0 1px 0 rgba(12, 12, 13, 1); - box-shadow: 0 1px 0 var(--toolbar-border-color); - } +* { + padding: 0; + margin: 0; } -#toolbarViewer { - height: 32px; +html, +body { + height: 100%; + width: 100%; } -#loadingBar { - position: relative; - width: 100%; - height: 4px; - background-color: rgba(237, 237, 240, 1); +body { background-color: var(--body-bg-color); - border-bottom: 1px solid rgba(204, 204, 204, 1); - border-bottom: 1px solid var(--toolbar-border-color); } -@media (prefers-color-scheme: dark) { - - #loadingBar { - border-bottom: 1px solid rgba(12, 12, 13, 1); - border-bottom: 1px solid var(--toolbar-border-color); - } +body, +input, +button, +select { + font: message-box; + outline: none; + scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); } -@media (prefers-color-scheme: dark) { - - #loadingBar { - background-color: rgba(42, 42, 46, 1); - background-color: var(--body-bg-color); - } +.hidden, +[hidden] { + display: none !important; } -#loadingBar .progress { - position: absolute; +#viewerContainer.pdfPresentationMode:-webkit-full-screen { top: 0; - left: 0; - width: 0%; + background-color: rgba(0, 0, 0, 1); + width: 100%; height: 100%; - background-color: rgba(10, 132, 255, 1); - background-color: var(--progressBar-color); overflow: hidden; - transition: width 200ms; -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress { - background-color: rgba(0, 96, 223, 1); - background-color: var(--progressBar-color); - } -} - -@-webkit-keyframes progressIndeterminate { - 0% { - left: -142px; - } - 100% { - left: 0; - } -} - -@keyframes progressIndeterminate { - 0% { - left: -142px; - } - 100% { - left: 0; - } -} - -#loadingBar .progress.indeterminate { - background-color: rgba(221, 221, 222, 1); - background-color: var(--progressBar-indeterminate-bg-color); - transition: none; -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate { - background-color: rgba(40, 40, 43, 1); - background-color: var(--progressBar-indeterminate-bg-color); - } + cursor: none; + -webkit-user-select: none; + user-select: none; } -#loadingBar .progress.indeterminate .glimmer { - position: absolute; +#viewerContainer.pdfPresentationMode:fullscreen { top: 0; - left: 0; + background-color: rgba(0, 0, 0, 1); + width: 100%; height: 100%; - width: calc(100% + 150px); - background: repeating-linear-gradient( - 135deg, - rgba(116, 177, 239, 1) 0, - rgba(221, 221, 222, 1) 5px, - rgba(221, 221, 222, 1) 45px, - rgba(10, 132, 255, 1) 55px, - rgba(10, 132, 255, 1) 95px, - rgba(116, 177, 239, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - -webkit-animation: progressIndeterminate 1s linear infinite; - animation: progressIndeterminate 1s linear infinite; -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -@media (prefers-color-scheme: dark) { - - #loadingBar .progress.indeterminate .glimmer { - background: repeating-linear-gradient( - 135deg, - rgba(20, 68, 133, 1) 0, - rgba(40, 40, 43, 1) 5px, - rgba(40, 40, 43, 1) 45px, - rgba(0, 96, 223, 1) 55px, - rgba(0, 96, 223, 1) 95px, - rgba(20, 68, 133, 1) 100px - ); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-indeterminate-blend-color) 0, - var(--progressBar-indeterminate-bg-color) 5px, - var(--progressBar-indeterminate-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-indeterminate-blend-color) 100px - ); - } -} - -.findbar, -.secondaryToolbar { - top: 32px; - position: absolute; - z-index: 10000; - height: auto; - min-width: 16px; - padding: 0px 4px 0px 4px; - margin: 4px 2px 4px 2px; - color: rgba(217, 217, 217, 1); - font-size: 12px; - line-height: 14px; - text-align: left; - cursor: default; -} - -.findbar { - min-width: 300px; - background-color: rgba(249, 249, 250, 1); - background-color: var(--toolbar-bg-color); + overflow: hidden; + cursor: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; } -@media (prefers-color-scheme: dark) { - - .findbar { - background-color: rgba(56, 56, 61, 1); - background-color: var(--toolbar-bg-color); - } -} -.findbar > div { - height: 32px; -} -.findbar.wrapContainers > div { - clear: both; -} -.findbar.wrapContainers > div#findbarMessageContainer { - height: auto; -} -html[dir="ltr"] .findbar { - left: 64px; -} -html[dir="rtl"] .findbar { - right: 64px; +.pdfPresentationMode:-webkit-full-screen a:not(.internalLink) { + display: none; } -html[dir="ltr"] .findbar .splitToolbarButton { - margin-left: 0px; - margin-top: 3px; +.pdfPresentationMode:fullscreen a:not(.internalLink) { + display: none; } - -html[dir="rtl"] .findbar .splitToolbarButton { - margin-right: 0px; - margin-top: 3px; -} - -.findbar .splitToolbarButton .findNext { - width: 29px; -} - -html[dir="ltr"] .findbar .splitToolbarButton .findNext { - border-right: 1px solid rgba(187, 187, 188, 1); - border-right: 1px solid var(--field-border-color); -} - -@media (prefers-color-scheme: dark) { - - html[dir="ltr"] .findbar .splitToolbarButton .findNext { - border-right: 1px solid rgba(115, 115, 115, 1); - border-right: 1px solid var(--field-border-color); - } -} - -html[dir="rtl"] .findbar .splitToolbarButton .findNext { - border-left: 1px solid rgba(187, 187, 188, 1); - border-left: 1px solid var(--field-border-color); -} - -@media (prefers-color-scheme: dark) { - - html[dir="rtl"] .findbar .splitToolbarButton .findNext { - border-left: 1px solid rgba(115, 115, 115, 1); - border-left: 1px solid var(--field-border-color); - } -} - -.findbar .splitToolbarButton .toolbarButton { - background-color: rgba(227, 228, 230, 1); - background-color: var(--findbar-nextprevious-btn-bg-color); - border-radius: 0px; - height: 26px; - border-top: 1px solid rgba(187, 187, 188, 1); - border-top: 1px solid var(--field-border-color); - border-bottom: 1px solid rgba(187, 187, 188, 1); - border-bottom: 1px solid var(--field-border-color); -} - -@media (prefers-color-scheme: dark) { - - .findbar .splitToolbarButton .toolbarButton { - border-bottom: 1px solid rgba(115, 115, 115, 1); - border-bottom: 1px solid var(--field-border-color); - } -} - -@media (prefers-color-scheme: dark) { - - .findbar .splitToolbarButton .toolbarButton { - border-top: 1px solid rgba(115, 115, 115, 1); - border-top: 1px solid var(--field-border-color); - } -} - -@media (prefers-color-scheme: dark) { - - .findbar .splitToolbarButton .toolbarButton { - background-color: rgba(89, 89, 89, 1); - background-color: var(--findbar-nextprevious-btn-bg-color); - } -} - -.findbar .splitToolbarButton .toolbarButton::before { - top: 5px; -} - -html[dir="ltr"] .findbar .splitToolbarButton > .findPrevious { - border-radius: 0; -} -html[dir="ltr"] .findbar .splitToolbarButton > .findNext { - border-bottom-left-radius: 0; - border-bottom-right-radius: 2px; - border-top-left-radius: 0; - border-top-right-radius: 2px; -} - -html[dir="rtl"] .findbar .splitToolbarButton > .findPrevious { - border-radius: 0; -} -html[dir="rtl"] .findbar .splitToolbarButton > .findNext { - border-bottom-left-radius: 2px; - border-bottom-right-radius: 0; - border-top-left-radius: 2px; - border-top-right-radius: 0; -} - -.findbar input[type="checkbox"] { - pointer-events: none; -} - -.findbar label { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.findbar label:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); -} - -@media (prefers-color-scheme: dark) { - - .findbar label:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } -} - -.findbar input:focus + label { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); -} - -@media (prefers-color-scheme: dark) { - - .findbar input:focus + label { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } -} - -html[dir="ltr"] #findInput { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -html[dir="rtl"] #findInput { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.findbar .toolbarField[type="checkbox"]:checked + .toolbarLabel { - background-color: rgba(0, 0, 0, 0.3) !important; - background-color: var(--toggled-btn-bg-color) !important; -} - -@media (prefers-color-scheme: dark) { - - .findbar .toolbarField[type="checkbox"]:checked + .toolbarLabel { - background-color: rgba(0, 0, 0, 0.3) !important; - background-color: var(--toggled-btn-bg-color) !important; - } -} - -#findInput { - width: 200px; -} -#findInput::-webkit-input-placeholder { - color: rgba(191, 191, 191, 1); -} -#findInput::-moz-placeholder { - font-style: normal; -} -#findInput:-ms-input-placeholder { - font-style: normal; -} -#findInput::-ms-input-placeholder { - font-style: normal; -} -#findInput::placeholder { - font-style: normal; -} -#findInput[data-status="pending"] { - background-image: url(images/loading.svg); - /*background-image: var(--loading-icon);*/ - background-repeat: no-repeat; - background-position: 98%; -} -@media (prefers-color-scheme: dark) { - - #findInput[data-status="pending"] { - background-image: url(images/loading-dark.svg); - /*background-image: var(--loading-icon);*/ - } -} -html[dir="rtl"] #findInput[data-status="pending"] { - background-position: 3px; -} - -.secondaryToolbar { - padding: 6px 0 10px 0; - height: auto; - z-index: 30000; - background-color: rgba(255, 255, 255, 1); - background-color: var(--doorhanger-bg-color); -} - -@media (prefers-color-scheme: dark) { - - .secondaryToolbar { - background-color: rgba(74, 74, 79, 1); - background-color: var(--doorhanger-bg-color); - } -} -html[dir="ltr"] .secondaryToolbar { - right: 4px; -} -html[dir="rtl"] .secondaryToolbar { - left: 4px; -} - -#secondaryToolbarButtonContainer { - max-width: 220px; - max-height: 400px; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - margin-bottom: -4px; -} - -#secondaryToolbarButtonContainer.hiddenScrollModeButtons > .scrollModeButtons, -#secondaryToolbarButtonContainer.hiddenSpreadModeButtons > .spreadModeButtons { - display: none !important; -} - -.doorHanger { - border-radius: 2px; - box-shadow: 0 1px 5px rgba(12, 12, 13, 0.2), - 0 0 0 1px rgba(12, 12, 13, 0.2); - box-shadow: 0 1px 5px var(--doorhanger-border-color), - 0 0 0 1px var(--doorhanger-border-color); -} - -@media (prefers-color-scheme: dark) { - - .doorHanger { - box-shadow: 0 1px 5px rgba(39, 39, 43, 1), - 0 0 0 1px rgba(39, 39, 43, 1); - box-shadow: 0 1px 5px var(--doorhanger-border-color), - 0 0 0 1px var(--doorhanger-border-color); - } -} - -.doorHangerRight { - border-radius: 2px; - box-shadow: 0 1px 5px rgba(12, 12, 13, 0.2), - 0 0 0 1px rgba(12, 12, 13, 0.2); - box-shadow: 0 1px 5px var(--doorhanger-border-color), - 0 0 0 1px var(--doorhanger-border-color); -} - -@media (prefers-color-scheme: dark) { - - .doorHangerRight { - box-shadow: 0 1px 5px rgba(39, 39, 43, 1), - 0 0 0 1px rgba(39, 39, 43, 1); - box-shadow: 0 1px 5px var(--doorhanger-border-color), - 0 0 0 1px var(--doorhanger-border-color); - } -} -.doorHanger:after, -.doorHanger:before, -.doorHangerRight:after, -.doorHangerRight:before { - bottom: 100%; - border: solid rgba(0, 0, 0, 0); - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; -} -.doorHanger:after, -.doorHangerRight:after { - border-width: 8px; -} -.doorHanger:after { - border-bottom-color: rgba(249, 249, 250, 1); - border-bottom-color: var(--toolbar-bg-color); -} -@media (prefers-color-scheme: dark) { - - .doorHanger:after { - border-bottom-color: rgba(56, 56, 61, 1); - border-bottom-color: var(--toolbar-bg-color); - } -} -.doorHangerRight:after { - border-bottom-color: rgba(255, 255, 255, 1); - border-bottom-color: var(--doorhanger-bg-color); -} -@media (prefers-color-scheme: dark) { - - .doorHangerRight:after { - border-bottom-color: rgba(74, 74, 79, 1); - border-bottom-color: var(--doorhanger-bg-color); - } -} -.doorHanger:before { - border-bottom-color: rgba(12, 12, 13, 0.2); - border-bottom-color: var(--doorhanger-border-color); - border-width: 9px; -} -@media (prefers-color-scheme: dark) { - - .doorHanger:before { - border-bottom-color: rgba(39, 39, 43, 1); - border-bottom-color: var(--doorhanger-border-color); - } -} -.doorHangerRight:before { - border-bottom-color: rgba(12, 12, 13, 0.2); - border-bottom-color: var(--doorhanger-border-color); - border-width: 9px; -} -@media (prefers-color-scheme: dark) { - - .doorHangerRight:before { - border-bottom-color: rgba(39, 39, 43, 1); - border-bottom-color: var(--doorhanger-border-color); - } -} - -html[dir="ltr"] .doorHanger:after, -html[dir="rtl"] .doorHangerRight:after { - left: 10px; - margin-left: -8px; -} - -html[dir="ltr"] .doorHanger:before, -html[dir="rtl"] .doorHangerRight:before { - left: 10px; - margin-left: -9px; -} - -html[dir="rtl"] .doorHanger:after, -html[dir="ltr"] .doorHangerRight:after { - right: 10px; - margin-right: -8px; -} - -html[dir="rtl"] .doorHanger:before, -html[dir="ltr"] .doorHangerRight:before { - right: 10px; - margin-right: -9px; -} - -#findResultsCount { - background-color: rgba(217, 217, 217, 1); - color: rgba(82, 82, 82, 1); - text-align: center; - padding: 3px 4px; - margin: 5px; -} - -#findMsg { - color: rgba(251, 0, 0, 1); -} -#findMsg:empty { - display: none; -} - -#findInput.notFound { - background-color: rgba(255, 102, 102, 1); -} - -#toolbarViewerMiddle { - position: absolute; - left: 50%; - transform: translateX(-50%); -} - -html[dir="ltr"] #toolbarViewerLeft, -html[dir="rtl"] #toolbarViewerRight { - float: left; -} -html[dir="ltr"] #toolbarViewerRight, -html[dir="rtl"] #toolbarViewerLeft { - float: right; -} -html[dir="ltr"] #toolbarViewerLeft > *, -html[dir="ltr"] #toolbarViewerMiddle > *, -html[dir="ltr"] #toolbarViewerRight > *, -html[dir="ltr"] .findbar * { - position: relative; - float: left; -} -html[dir="rtl"] #toolbarViewerLeft > *, -html[dir="rtl"] #toolbarViewerMiddle > *, -html[dir="rtl"] #toolbarViewerRight > *, -html[dir="rtl"] .findbar * { - position: relative; - float: right; -} - -html[dir="ltr"] .splitToolbarButton { - margin: 2px 2px 0; - display: inline-block; -} -html[dir="rtl"] .splitToolbarButton { - margin: 2px 2px 0; - display: inline-block; -} -html[dir="ltr"] .splitToolbarButton > .toolbarButton { - border-radius: 2px; - float: left; -} -html[dir="rtl"] .splitToolbarButton > .toolbarButton { - border-radius: 2px; - float: right; -} - -.toolbarButton, -.secondaryToolbarButton, -.overlayButton { - border: 0 none; - background: none; - width: 28px; - height: 28px; + +.pdfPresentationMode:-webkit-full-screen .textLayer span { + cursor: none; } -.overlayButton { - background-color: rgba(12, 12, 13, 0.1); - background-color: var(--overlay-button-bg-color); + +.pdfPresentationMode:fullscreen .textLayer span { + cursor: none; } -@media (prefers-color-scheme: dark) { - .overlayButton { - background-color: rgba(92, 92, 97, 1); - background-color: var(--overlay-button-bg-color); - } +.pdfPresentationMode.pdfPresentationModeControls > *, +.pdfPresentationMode.pdfPresentationModeControls .textLayer span { + cursor: default; } -.overlayButton:hover { - background-color: rgba(12, 12, 13, 0.3); - background-color: var(--overlay-button-hover-color); +#outerContainer { + width: 100%; + height: 100%; + position: relative; } -@media (prefers-color-scheme: dark) { +[dir="ltr"] #sidebarContainer { + left: calc(-1 * var(--sidebar-width)); +} - .overlayButton:hover { - background-color: rgba(115, 115, 115, 1); - background-color: var(--overlay-button-hover-color); - } +[dir="rtl"] #sidebarContainer { + right: calc(-1 * var(--sidebar-width)); } -.overlayButton:focus { - background-color: rgba(12, 12, 13, 0.3); - background-color: var(--overlay-button-hover-color); +[dir="ltr"] #sidebarContainer { + border-right: var(--doorhanger-border-color-whcm); } -@media (prefers-color-scheme: dark) { +[dir="rtl"] #sidebarContainer { + border-left: var(--doorhanger-border-color-whcm); +} - .overlayButton:focus { - background-color: rgba(115, 115, 115, 1); - background-color: var(--overlay-button-hover-color); - } +[dir="ltr"] #sidebarContainer { + transition-property: left; } -.toolbarButton > span { - display: inline-block; - width: 0; - height: 0; - overflow: hidden; +[dir="rtl"] #sidebarContainer { + transition-property: right; } -.toolbarButton[disabled], -.secondaryToolbarButton[disabled], -.overlayButton[disabled] { - opacity: 0.5; +#sidebarContainer { + position: absolute; + top: 32px; + bottom: 0; + inset-inline-start: calc(-1 * var(--sidebar-width)); + width: var(--sidebar-width); + visibility: hidden; + z-index: 100; + border-top: 1px solid rgba(51, 51, 51, 1); + -webkit-border-end: var(--doorhanger-border-color-whcm); + border-inline-end: var(--doorhanger-border-color-whcm); + transition-property: inset-inline-start; + transition-duration: var(--sidebar-transition-duration); + transition-timing-function: var(--sidebar-transition-timing-function); } -.splitToolbarButton.toggled .toolbarButton { - margin: 0; +#outerContainer.sidebarMoving #sidebarContainer, +#outerContainer.sidebarOpen #sidebarContainer { + visibility: visible; +} +[dir="ltr"] #outerContainer.sidebarOpen #sidebarContainer { + left: 0; +} +[dir="rtl"] #outerContainer.sidebarOpen #sidebarContainer { + right: 0; +} +#outerContainer.sidebarOpen #sidebarContainer { + inset-inline-start: 0; } -.splitToolbarButton > .toolbarButton:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); - z-index: 199; +#mainContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + min-width: 350px; } -@media (prefers-color-scheme: dark) { +[dir="ltr"] #sidebarContent { + left: 0; +} - .splitToolbarButton > .toolbarButton:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="rtl"] #sidebarContent { + right: 0; } -.splitToolbarButton > .toolbarButton:focus { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); - z-index: 199; +#sidebarContent { + top: 32px; + bottom: 0; + inset-inline-start: 0; + overflow: auto; + position: absolute; + width: 100%; + background-color: rgba(0, 0, 0, 0.1); + box-shadow: inset calc(-1px * var(--dir-factor)) 0 0 rgba(0, 0, 0, 0.25); } -@media (prefers-color-scheme: dark) { +#viewerContainer { + overflow: auto; + position: absolute; + top: 32px; + right: 0; + bottom: 0; + left: 0; + outline: none; +} +#viewerContainer:not(.pdfPresentationMode) { + transition-duration: var(--sidebar-transition-duration); + transition-timing-function: var(--sidebar-transition-timing-function); +} - .splitToolbarButton > .toolbarButton:focus { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="ltr"] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) { + left: var(--sidebar-width); } -.dropdownToolbarButton:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); - z-index: 199; +[dir="rtl"] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) { + right: var(--sidebar-width); } -@media (prefers-color-scheme: dark) { +[dir="ltr"] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) { + transition-property: left; +} - .dropdownToolbarButton:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="rtl"] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) { + transition-property: right; } -.toolbarButton.textButton:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); - z-index: 199; +#outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) { + inset-inline-start: var(--sidebar-width); + transition-property: inset-inline-start; } -@media (prefers-color-scheme: dark) { +.toolbar { + position: relative; + left: 0; + right: 0; + z-index: 9999; + cursor: default; +} - .toolbarButton.textButton:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +#toolbarContainer { + width: 100%; } -.toolbarButton.textButton:focus { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); - z-index: 199; +#toolbarSidebar { + width: 100%; + height: 32px; + background-color: var(--sidebar-toolbar-bg-color); + box-shadow: inset calc(-1px * var(--dir-factor)) 0 0 rgba(0, 0, 0, 0.25), + 0 1px 0 rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.1); } -@media (prefers-color-scheme: dark) { +[dir="ltr"] #sidebarResizer { + right: -6px; +} - .toolbarButton.textButton:focus { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="rtl"] #sidebarResizer { + left: -6px; } -.splitToolbarButton > .toolbarButton { - position: relative; + +#sidebarResizer { + position: absolute; + top: 0; + bottom: 0; + inset-inline-end: -6px; + width: 6px; + z-index: 200; + cursor: ew-resize; } -html[dir="ltr"] .splitToolbarButton > .toolbarButton:first-child, -html[dir="rtl"] .splitToolbarButton > .toolbarButton:last-child { + +#toolbarContainer, +.findbar, +.secondaryToolbar, +.editorParamsToolbar { position: relative; - margin: 0; + height: 32px; + background-color: var(--toolbar-bg-color); + box-shadow: 0 1px 0 var(--toolbar-border-color); } -html[dir="ltr"] .splitToolbarButton > .toolbarButton:last-child, -html[dir="rtl"] .splitToolbarButton > .toolbarButton:first-child { - position: relative; - margin: 0; + +#toolbarViewer { + height: 32px; } -.splitToolbarButtonSeparator { - padding: 10px 0; - width: 1px; - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--separator-color); - z-index: 99; - display: inline-block; - margin: 4px 0; + +[dir="ltr"] #loadingBar { + left: 0; + right: var(--progressBar-end-offset); } -@media (prefers-color-scheme: dark) { - .splitToolbarButtonSeparator { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--separator-color); - } +[dir="rtl"] #loadingBar { + right: 0; + left: var(--progressBar-end-offset); } -.findbar .splitToolbarButtonSeparator { - background-color: rgba(187, 187, 188, 1); - background-color: var(--field-border-color); - margin: 0; - padding: 13px 0; +[dir="ltr"] #loadingBar { + transition-property: left; } -@media (prefers-color-scheme: dark) { +[dir="rtl"] #loadingBar { + transition-property: right; +} - .findbar .splitToolbarButtonSeparator { - background-color: rgba(115, 115, 115, 1); - background-color: var(--field-border-color); - } +#loadingBar { + position: absolute; + inset-inline: 0 var(--progressBar-end-offset); + height: 4px; + background-color: var(--body-bg-color); + border-bottom: 1px solid var(--toolbar-border-color); + transition-property: inset-inline-start; + transition-duration: var(--sidebar-transition-duration); + transition-timing-function: var(--sidebar-transition-timing-function); } -html[dir="ltr"] .splitToolbarButtonSeparator { - float: left; +[dir="ltr"] #outerContainer.sidebarOpen #loadingBar { + left: var(--sidebar-width); } -html[dir="rtl"] .splitToolbarButtonSeparator { - float: right; + +[dir="rtl"] #outerContainer.sidebarOpen #loadingBar { + right: var(--sidebar-width); } -.toolbarButton { - min-width: 16px; - padding: 2px 6px 0; - border: none; - border-radius: 2px; - color: rgba(12, 12, 13, 1); - color: var(--main-color); - font-size: 12px; - line-height: 14px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Opera does not support user-select, use <... unselectable="on"> instead */ - cursor: default; - box-sizing: border-box; +#outerContainer.sidebarOpen #loadingBar { + inset-inline-start: var(--sidebar-width); } -@media (prefers-color-scheme: dark) { +#loadingBar .progress { + position: absolute; + top: 0; + left: 0; + width: 100%; + transform: scaleX(var(--progressBar-percent)); + transform-origin: 0 0; + height: 100%; + background-color: var(--progressBar-color); + overflow: hidden; + transition: transform 200ms; +} - .toolbarButton { - color: rgba(249, 249, 250, 1); - color: var(--main-color); +@-webkit-keyframes progressIndeterminate { + 0% { + transform: translateX(-142px); + } + 100% { + transform: translateX(0); } } -.dropdownToolbarButton { - min-width: 16px; - padding: 2px 6px 0; - border: none; - border-radius: 2px; - color: rgba(12, 12, 13, 1); - color: var(--main-color); - font-size: 12px; - line-height: 14px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Opera does not support user-select, use <... unselectable="on"> instead */ - cursor: default; - box-sizing: border-box; +@keyframes progressIndeterminate { + 0% { + transform: translateX(-142px); + } + 100% { + transform: translateX(0); + } } -@media (prefers-color-scheme: dark) { +#loadingBar.indeterminate .progress { + transform: none; + background-color: var(--progressBar-indeterminate-bg-color); + transition: none; +} - .dropdownToolbarButton { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +#loadingBar.indeterminate .progress .glimmer { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: calc(100% + 150px); + background: repeating-linear-gradient( + 135deg, + var(--progressBar-indeterminate-blend-color) 0, + var(--progressBar-indeterminate-bg-color) 5px, + var(--progressBar-indeterminate-bg-color) 45px, + var(--progressBar-color) 55px, + var(--progressBar-color) 95px, + var(--progressBar-indeterminate-blend-color) 100px + ); + -webkit-animation: progressIndeterminate 1s linear infinite; + animation: progressIndeterminate 1s linear infinite; } -.secondaryToolbarButton { - min-width: 16px; - padding: 2px 6px 0; - border: none; - border-radius: 2px; - color: rgba(12, 12, 13, 1); - color: var(--main-color); - font-size: 12px; - line-height: 14px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Opera does not support user-select, use <... unselectable="on"> instead */ +#outerContainer.sidebarResizing #sidebarContainer, +#outerContainer.sidebarResizing #viewerContainer, +#outerContainer.sidebarResizing #loadingBar { + /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */ + transition-duration: 0s; +} + +.findbar, +.secondaryToolbar, +.editorParamsToolbar { + top: 32px; + position: absolute; + z-index: 10000; + height: auto; + padding: 0 4px; + margin: 4px 2px; + font-size: 12px; + line-height: 14px; + text-align: left; cursor: default; - box-sizing: border-box; } -@media (prefers-color-scheme: dark) { +[dir="ltr"] .findbar { + left: 64px; +} - .secondaryToolbarButton { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +[dir="rtl"] .findbar { + right: 64px; } -.overlayButton { - min-width: 16px; - padding: 2px 6px 0; - border: none; - border-radius: 2px; - color: rgba(12, 12, 13, 1); - color: var(--main-color); - font-size: 12px; - line-height: 14px; +.findbar { + inset-inline-start: 64px; + min-width: 300px; + background-color: var(--toolbar-bg-color); +} +.findbar > div { + height: 32px; +} +[dir="ltr"] .findbar > div#findbarInputContainer { + margin-right: 4px; +} +[dir="rtl"] .findbar > div#findbarInputContainer { + margin-left: 4px; +} +.findbar > div#findbarInputContainer { + -webkit-margin-end: 4px; + margin-inline-end: 4px; +} +.findbar.wrapContainers > div, +.findbar.wrapContainers > div#findbarMessageContainer > * { + clear: both; +} +.findbar.wrapContainers > div#findbarMessageContainer { + height: auto; +} + +.findbar input[type="checkbox"] { + pointer-events: none; +} + +.findbar label { -webkit-user-select: none; -moz-user-select: none; - -ms-user-select: none; user-select: none; - /* Opera does not support user-select, use <... unselectable="on"> instead */ - cursor: default; - box-sizing: border-box; } -@media (prefers-color-scheme: dark) { +.findbar label:hover, +.findbar input:focus-visible + label { + color: var(--toggled-btn-color); + background-color: var(--button-hover-color); +} - .overlayButton { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +.findbar .toolbarField[type="checkbox"]:checked + .toolbarLabel { + background-color: var(--toggled-btn-bg-color) !important; + color: var(--toggled-btn-color); } -html[dir="ltr"] .toolbarButton, -html[dir="ltr"] .overlayButton, -html[dir="ltr"] .dropdownToolbarButton { - margin: 2px 1px; +#findInput { + width: 200px; } -html[dir="rtl"] .toolbarButton, -html[dir="rtl"] .overlayButton, -html[dir="rtl"] .dropdownToolbarButton { - margin: 2px 1px; +#findInput::-moz-placeholder { + font-style: normal; } - -html[dir="ltr"] #toolbarViewerLeft > .toolbarButton:first-child, -html[dir="rtl"] #toolbarViewerRight > .toolbarButton:last-child { - margin-left: 2px; +#findInput::placeholder { + font-style: normal; } - -html[dir="ltr"] #toolbarViewerRight > .toolbarButton:last-child, -html[dir="rtl"] #toolbarViewerLeft > .toolbarButton:first-child { - margin-right: 2px; +#findInput[data-status="pending"] { + background-image: var(--loading-icon); + background-repeat: no-repeat; + background-position: calc(50% + 48% * var(--dir-factor)); } -.toolbarButton:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); +#findInput[data-status="notFound"] { + background-color: rgba(255, 102, 102, 1); } -@media (prefers-color-scheme: dark) { - .toolbarButton:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="ltr"] .secondaryToolbar,[dir="ltr"] +.editorParamsToolbar { + right: 4px; } -.toolbarButton:focus { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); + +[dir="rtl"] .secondaryToolbar,[dir="rtl"] +.editorParamsToolbar { + left: 4px; } -@media (prefers-color-scheme: dark) { - .toolbarButton:focus { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +.secondaryToolbar, +.editorParamsToolbar { + padding: 6px 0 10px; + inset-inline-end: 4px; + height: auto; + z-index: 30000; + background-color: var(--doorhanger-bg-color); } -.secondaryToolbarButton:hover { - background-color: rgba(237, 237, 237, 1); - background-color: var(--doorhanger-hover-color); + +.editorParamsToolbarContainer { + width: 220px; + margin-bottom: -4px; } -@media (prefers-color-scheme: dark) { - .secondaryToolbarButton:hover { - background-color: rgba(93, 94, 98, 1); - background-color: var(--doorhanger-hover-color); - } +.editorParamsToolbarContainer > .editorParamsSetter { + min-height: 26px; + display: flex; + align-items: center; + justify-content: space-between; + padding-left: 10px; + padding-right: 10px; + padding-inline: 10px; } -.secondaryToolbarButton:focus { - background-color: rgba(237, 237, 237, 1); - background-color: var(--doorhanger-hover-color); + +[dir="ltr"] .editorParamsToolbarContainer .editorParamsLabel { + padding-right: 10px; } -@media (prefers-color-scheme: dark) { - .secondaryToolbarButton:focus { - background-color: rgba(93, 94, 98, 1); - background-color: var(--doorhanger-hover-color); - } +[dir="rtl"] .editorParamsToolbarContainer .editorParamsLabel { + padding-left: 10px; } -.toolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); +.editorParamsToolbarContainer .editorParamsLabel { + -webkit-padding-end: 10px; + padding-inline-end: 10px; + flex: none; + color: var(--main-color); } -@media (prefers-color-scheme: dark) { +.editorParamsToolbarContainer .editorParamsColor { + width: 32px; + height: 32px; + flex: none; +} - .toolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); - } +.editorParamsToolbarContainer .editorParamsSlider { + background-color: transparent; + width: 90px; + flex: 0 1 0; } -.splitToolbarButton.toggled > .toolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); +.editorParamsToolbarContainer .editorParamsSlider::-moz-range-progress { + background-color: black; } -@media (prefers-color-scheme: dark) { +.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-runnable-track, +.editorParamsToolbarContainer .editorParamsSlider::-moz-range-track { + background-color: black; +} - .splitToolbarButton.toggled > .toolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); - } +.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-thumb, +.editorParamsToolbarContainer .editorParamsSlider::-moz-range-thumb { + background-color: white; } -.secondaryToolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); +#secondaryToolbarButtonContainer { + max-width: 220px; + min-height: 26px; + max-height: calc(var(--viewer-container-height) - 40px); + overflow-y: auto; + margin-bottom: -4px; } -@media (prefers-color-scheme: dark) { +[dir="ltr"] #editorInkParamsToolbar { + right: 40px; +} - .secondaryToolbarButton.toggled { - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--toggled-btn-bg-color); - } +[dir="rtl"] #editorInkParamsToolbar { + left: 40px; } -.toolbarButton.toggled:hover:active, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active, -.secondaryToolbarButton.toggled:hover:active { - background-color: rgba(0, 0, 0, 0.4); +#editorInkParamsToolbar { + inset-inline-end: 40px; + background-color: var(--toolbar-bg-color); } -.dropdownToolbarButton { - width: 140px; - padding: 0; - overflow: hidden; - background-color: rgba(215, 215, 219, 1); - background-color: var(--dropdown-btn-bg-color); - margin-top: 2px !important; +[dir="ltr"] #editorFreeTextParamsToolbar { + right: 68px; } -@media (prefers-color-scheme: dark) { +[dir="rtl"] #editorFreeTextParamsToolbar { + left: 68px; +} - .dropdownToolbarButton { - background-color: rgba(74, 74, 79, 1); - background-color: var(--dropdown-btn-bg-color); - } +#editorFreeTextParamsToolbar { + inset-inline-end: 68px; + background-color: var(--toolbar-bg-color); } -.dropdownToolbarButton::after { + +.doorHanger, +.doorHangerRight { + border-radius: 2px; + box-shadow: 0 1px 5px var(--doorhanger-border-color), + 0 0 0 1px var(--doorhanger-border-color); + border: var(--doorhanger-border-color-whcm); +} +.doorHanger:after, +.doorHanger:before, +.doorHangerRight:after, +.doorHangerRight:before { + bottom: 100%; + border: 8px solid rgba(0, 0, 0, 0); + content: " "; + height: 0; + width: 0; position: absolute; - display: inline-block; - top: 6px; - content: url(images/toolbarButton-menuArrow.svg); - /*content: var(--toolbarButton-menuArrow-icon);*/ pointer-events: none; - max-width: 16px; + opacity: var(--doorhanger-triangle-opacity-whcm); } -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton::after { - content: url(images/toolbarButton-menuArrow-dark.svg); - /*content: var(--toolbarButton-menuArrow-icon);*/ - } +[dir="ltr"] .doorHanger:after { + left: 10px; } -html[dir="ltr"] .dropdownToolbarButton::after { - right: 7px; +[dir="rtl"] .doorHanger:after { + right: 10px; } -html[dir="rtl"] .dropdownToolbarButton::after { - left: 7px; +[dir="ltr"] .doorHanger:after { + margin-left: -8px; } - -.dropdownToolbarButton > select { - width: 162px; - height: 28px; - font-size: 12px; - color: rgba(12, 12, 13, 1); - color: var(--main-color); - margin: 0; - padding: 1px 0 2px; - border: none; - background-color: rgba(215, 215, 219, 1); - background-color: var(--dropdown-btn-bg-color); +[dir="rtl"] .doorHanger:after { + margin-right: -8px; } - -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton > select { - background-color: rgba(74, 74, 79, 1); - background-color: var(--dropdown-btn-bg-color); - } +.doorHanger:after { + inset-inline-start: 10px; + -webkit-margin-start: -8px; + margin-inline-start: -8px; + border-bottom-color: var(--toolbar-bg-color); } - -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton > select { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +[dir="ltr"] .doorHangerRight:after { + right: 10px; } -html[dir="ltr"] .dropdownToolbarButton > select { - padding-left: 4px; +[dir="rtl"] .doorHangerRight:after { + left: 10px; } -html[dir="rtl"] .dropdownToolbarButton > select { - padding-right: 4px; +[dir="ltr"] .doorHangerRight:after { + margin-right: -8px; } -.dropdownToolbarButton > select:hover { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); +[dir="rtl"] .doorHangerRight:after { + margin-left: -8px; } -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton > select:hover { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +.doorHangerRight:after { + inset-inline-end: 10px; + -webkit-margin-end: -8px; + margin-inline-end: -8px; + border-bottom-color: var(--doorhanger-bg-color); } - -.dropdownToolbarButton > select:focus { - background-color: rgba(221, 222, 223, 1); - background-color: var(--button-hover-color); +.doorHanger:before, +.doorHangerRight:before { + border-bottom-color: var(--doorhanger-border-color); + border-width: 9px; } - -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton > select:focus { - background-color: rgba(102, 102, 103, 1); - background-color: var(--button-hover-color); - } +[dir="ltr"] .doorHanger:before { + left: 10px; } - -.dropdownToolbarButton > select > option { - background: rgba(255, 255, 255, 1); - background: var(--doorhanger-bg-color); +[dir="rtl"] .doorHanger:before { + right: 10px; } - -@media (prefers-color-scheme: dark) { - - .dropdownToolbarButton > select > option { - background: rgba(74, 74, 79, 1); - background: var(--doorhanger-bg-color); - } +[dir="ltr"] .doorHanger:before { + margin-left: -9px; } - -#customScaleOption { - display: none; +[dir="rtl"] .doorHanger:before { + margin-right: -9px; } - -#pageWidthOption { - border-bottom: 1px rgba(255, 255, 255, 0.5) solid; +.doorHanger:before { + inset-inline-start: 10px; + -webkit-margin-start: -9px; + margin-inline-start: -9px; } - -.toolbarButtonSpacer { - width: 30px; - display: inline-block; - height: 1px; +[dir="ltr"] .doorHangerRight:before { + right: 10px; +} +[dir="rtl"] .doorHangerRight:before { + left: 10px; +} +[dir="ltr"] .doorHangerRight:before { + margin-right: -9px; +} +[dir="rtl"] .doorHangerRight:before { + margin-left: -9px; +} +.doorHangerRight:before { + inset-inline-end: 10px; + -webkit-margin-end: -9px; + margin-inline-end: -9px; } -html[dir="ltr"] #findPrevious { - margin-left: 0; +#findResultsCount { + background-color: rgba(217, 217, 217, 1); + color: rgba(82, 82, 82, 1); + text-align: center; + padding: 4px 5px; + margin: 5px; } -html[dir="ltr"] #findNext { - margin-right: 3px; + +#findMsg { + color: rgba(251, 0, 0, 1); } -html[dir="rtl"] #findPrevious { - margin-right: 0; +#findResultsCount:empty, +#findMsg:empty { + display: none; } -html[dir="rtl"] #findNext { - margin-left: 3px; + +#toolbarViewerMiddle { + position: absolute; + left: 50%; + transform: translateX(-50%); } -.toolbarButton::before { - opacity: 0.7; - opacity: var(--toolbar-icon-opacity); - top: 6px; +[dir="ltr"] #toolbarViewerLeft,[dir="ltr"] +#toolbarSidebarLeft { + float: left; } -.secondaryToolbarButton::before { - opacity: 0.9; - opacity: var(--doorhanger-icon-opacity); - top: 5px; +[dir="rtl"] #toolbarViewerLeft,[dir="rtl"] +#toolbarSidebarLeft { + float: right; } -.toolbarButton::before, -.secondaryToolbarButton::before { - /* All matching images have a size of 16x16 - * All relevant containers have a size of 28x28 */ - position: absolute; - display: inline-block; - left: 6px; - max-width: 16px; +#toolbarViewerLeft, +#toolbarSidebarLeft { + float: inline-start; +} +[dir="ltr"] #toolbarViewerRight,[dir="ltr"] +#toolbarSidebarRight { + float: right; } - -html[dir="ltr"] .secondaryToolbarButton::before { - left: 12px; +[dir="rtl"] #toolbarViewerRight,[dir="rtl"] +#toolbarSidebarRight { + float: left; } -html[dir="rtl"] .secondaryToolbarButton::before { - right: 12px; +#toolbarViewerRight, +#toolbarSidebarRight { + float: inline-end; } -.toolbarButton#sidebarToggle::before { - content: url(images/toolbarButton-sidebarToggle.svg); - /*content: var(--toolbarButton-sidebarToggle-icon);*/ +[dir="ltr"] #toolbarViewerLeft > *,[dir="ltr"] +#toolbarViewerMiddle > *,[dir="ltr"] +#toolbarViewerRight > *,[dir="ltr"] +#toolbarSidebarLeft *,[dir="ltr"] +#toolbarSidebarRight *,[dir="ltr"] +.findbar * { + float: left; } -@media (prefers-color-scheme: dark) { - - .toolbarButton#sidebarToggle::before { - content: url(images/toolbarButton-sidebarToggle-dark.svg); - /*content: var(--toolbarButton-sidebarToggle-icon);*/ - } +[dir="rtl"] #toolbarViewerLeft > *,[dir="rtl"] +#toolbarViewerMiddle > *,[dir="rtl"] +#toolbarViewerRight > *,[dir="rtl"] +#toolbarSidebarLeft *,[dir="rtl"] +#toolbarSidebarRight *,[dir="rtl"] +.findbar * { + float: right; } -html[dir="rtl"] .toolbarButton#sidebarToggle::before { - transform: scaleX(-1); + +#toolbarViewerLeft > *, +#toolbarViewerMiddle > *, +#toolbarViewerRight > *, +#toolbarSidebarLeft *, +#toolbarSidebarRight *, +.findbar * { + position: relative; + float: inline-start; } -.toolbarButton#secondaryToolbarToggle::before { - content: url(images/toolbarButton-secondaryToolbarToggle.svg); - /*content: var(--toolbarButton-secondaryToolbarToggle-icon);*/ +[dir="ltr"] #toolbarViewerLeft { + padding-left: 1px; } -@media (prefers-color-scheme: dark) { +[dir="rtl"] #toolbarViewerLeft { + padding-right: 1px; +} - .toolbarButton#secondaryToolbarToggle::before { - content: url(images/toolbarButton-secondaryToolbarToggle-dark.svg); - /*content: var(--toolbarButton-secondaryToolbarToggle-icon);*/ - } +#toolbarViewerLeft { + -webkit-padding-start: 1px; + padding-inline-start: 1px; } -html[dir="rtl"] .toolbarButton#secondaryToolbarToggle::before { - transform: scaleX(-1); +[dir="ltr"] #toolbarViewerRight { + padding-right: 1px; } - -.toolbarButton.findPrevious::before { - content: url(images/findbarButton-previous.svg); - /*content: var(--findbarButton-previous-icon);*/ +[dir="rtl"] #toolbarViewerRight { + padding-left: 1px; } - -@media (prefers-color-scheme: dark) { - - .toolbarButton.findPrevious::before { - content: url(images/findbarButton-previous-dark.svg); - /*content: var(--findbarButton-previous-icon);*/ - } +#toolbarViewerRight { + -webkit-padding-end: 1px; + padding-inline-end: 1px; } -html[dir="rtl"] .toolbarButton.findPrevious::before { - transform: scaleX(-1); +[dir="ltr"] #toolbarSidebarRight { + padding-right: 2px; } - -.toolbarButton.findNext::before { - content: url(images/findbarButton-next.svg); - /*content: var(--findbarButton-next-icon);*/ +[dir="rtl"] #toolbarSidebarRight { + padding-left: 2px; +} +#toolbarSidebarRight { + -webkit-padding-end: 2px; + padding-inline-end: 2px; } -@media (prefers-color-scheme: dark) { - - .toolbarButton.findNext::before { - content: url(images/findbarButton-next-dark.svg); - /*content: var(--findbarButton-next-icon);*/ - } +.splitToolbarButton { + margin: 2px; + display: inline-block; } -html[dir="rtl"] .toolbarButton.findNext::before { - transform: scaleX(-1); +[dir="ltr"] .splitToolbarButton > .toolbarButton { + float: left; } - -.toolbarButton.pageUp::before { - content: url(images/toolbarButton-pageUp.svg); - /*content: var(--toolbarButton-pageUp-icon);*/ +[dir="rtl"] .splitToolbarButton > .toolbarButton { + float: right; +} +.splitToolbarButton > .toolbarButton { + float: inline-start; } -@media (prefers-color-scheme: dark) { +.toolbarButton, +.secondaryToolbarButton, +.dialogButton { + border: 0 none; + background: none; + width: 28px; + height: 28px; +} - .toolbarButton.pageUp::before { - content: url(images/toolbarButton-pageUp-dark.svg); - /*content: var(--toolbarButton-pageUp-icon);*/ - } +.dialogButton:hover, +.dialogButton:focus-visible { + background-color: var(--dialog-button-hover-bg-color); } -html[dir="rtl"] .toolbarButton.pageUp::before { - transform: scaleX(-1); + +.dialogButton:hover > span, +.dialogButton:focus-visible > span { + color: var(--dialog-button-hover-color); } -.toolbarButton.pageDown::before { - content: url(images/toolbarButton-pageDown.svg); - /*content: var(--toolbarButton-pageDown-icon);*/ +.toolbarButton > span { + display: inline-block; + width: 0; + height: 0; + overflow: hidden; } -@media (prefers-color-scheme: dark) { +.toolbarButton[disabled], +.secondaryToolbarButton[disabled], +.dialogButton[disabled] { + opacity: 0.5; +} - .toolbarButton.pageDown::before { - content: url(images/toolbarButton-pageDown-dark.svg); - /*content: var(--toolbarButton-pageDown-icon);*/ - } +.splitToolbarButton > .toolbarButton:hover, +.splitToolbarButton > .toolbarButton:focus-visible, +.dropdownToolbarButton:hover { + background-color: var(--button-hover-color); } -html[dir="rtl"] .toolbarButton.pageDown::before { - transform: scaleX(-1); +.splitToolbarButton > .toolbarButton { + position: relative; + margin: 0; } - -.toolbarButton.zoomOut::before { - content: url(images/toolbarButton-zoomOut.svg); - /*content: var(--toolbarButton-zoomOut-icon);*/ +[dir="ltr"] #toolbarSidebar .splitToolbarButton > .toolbarButton { + margin-right: 2px; } - -@media (prefers-color-scheme: dark) { - - .toolbarButton.zoomOut::before { - content: url(images/toolbarButton-zoomOut-dark.svg); - /*content: var(--toolbarButton-zoomOut-icon);*/ - } +[dir="rtl"] #toolbarSidebar .splitToolbarButton > .toolbarButton { + margin-left: 2px; } - -.toolbarButton.zoomIn::before { - content: url(images/toolbarButton-zoomIn.svg); - /*content: var(--toolbarButton-zoomIn-icon);*/ +#toolbarSidebar .splitToolbarButton > .toolbarButton { + -webkit-margin-end: 2px; + margin-inline-end: 2px; } -@media (prefers-color-scheme: dark) { - - .toolbarButton.zoomIn::before { - content: url(images/toolbarButton-zoomIn-dark.svg); - /*content: var(--toolbarButton-zoomIn-icon);*/ - } +[dir="ltr"] .splitToolbarButtonSeparator { + float: left; } -.toolbarButton.presentationMode::before { - content: url(images/toolbarButton-presentationMode.svg); - /*content: var(--toolbarButton-presentationMode-icon);*/ +[dir="rtl"] .splitToolbarButtonSeparator { + float: right; } -@media (prefers-color-scheme: dark) { - - .toolbarButton.presentationMode::before { - content: url(images/toolbarButton-presentationMode-dark.svg); - /*content: var(--toolbarButton-presentationMode-icon);*/ - } +.splitToolbarButtonSeparator { + float: inline-start; + margin: 4px 0; + width: 1px; + height: 20px; + background-color: var(--separator-color); } -.secondaryToolbarButton.presentationMode::before { - content: url(images/toolbarButton-presentationMode.svg); - /*content: var(--toolbarButton-presentationMode-icon);*/ +.toolbarButton, +.dropdownToolbarButton, +.secondaryToolbarButton, +.dialogButton { + min-width: 16px; + margin: 2px 1px; + padding: 2px 6px 0; + border: none; + border-radius: 2px; + color: var(--main-color); + font-size: 12px; + line-height: 14px; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + cursor: default; + box-sizing: border-box; } -@media (prefers-color-scheme: dark) { +.toolbarButton:hover, +.toolbarButton:focus-visible { + background-color: var(--button-hover-color); +} +.secondaryToolbarButton:hover, +.secondaryToolbarButton:focus-visible { + background-color: var(--doorhanger-hover-bg-color); + color: var(--doorhanger-hover-color); +} - .secondaryToolbarButton.presentationMode::before { - content: url(images/toolbarButton-presentationMode-dark.svg); - /*content: var(--toolbarButton-presentationMode-icon);*/ - } +.toolbarButton.toggled, +.splitToolbarButton.toggled > .toolbarButton.toggled, +.secondaryToolbarButton.toggled { + background-color: var(--toggled-btn-bg-color); + color: var(--toggled-btn-color); } -.toolbarButton.print::before { - content: url(images/toolbarButton-print.svg); - /*content: var(--toolbarButton-print-icon);*/ +.toolbarButton.toggled::before, +.secondaryToolbarButton.toggled::before { + background-color: var(--toggled-btn-color); } -@media (prefers-color-scheme: dark) { +.toolbarButton.toggled:hover:active, +.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active, +.secondaryToolbarButton.toggled:hover:active { + background-color: var(--toggled-hover-active-btn-color); +} - .toolbarButton.print::before { - content: url(images/toolbarButton-print-dark.svg); - /*content: var(--toolbarButton-print-icon);*/ - } +.dropdownToolbarButton { + width: var(--scale-select-container-width); + padding: 0; + overflow: hidden; + background-color: var(--dropdown-btn-bg-color); +} +[dir="ltr"] .dropdownToolbarButton::after { + right: 7px; +} +[dir="rtl"] .dropdownToolbarButton::after { + left: 7px; +} +.dropdownToolbarButton::after { + top: 6px; + inset-inline-end: 7px; + pointer-events: none; + -webkit-mask-image: var(--toolbarButton-menuArrow-icon); + mask-image: var(--toolbarButton-menuArrow-icon); } -.secondaryToolbarButton.print::before { - content: url(images/toolbarButton-print.svg); - /*content: var(--toolbarButton-print-icon);*/ +[dir="ltr"] .dropdownToolbarButton > select { + padding-left: 4px; } -@media (prefers-color-scheme: dark) { +[dir="rtl"] .dropdownToolbarButton > select { + padding-right: 4px; +} - .secondaryToolbarButton.print::before { - content: url(images/toolbarButton-print-dark.svg); - /*content: var(--toolbarButton-print-icon);*/ - } +.dropdownToolbarButton > select { + width: calc( + var(--scale-select-container-width) + var(--scale-select-overflow) + ); + height: 28px; + font-size: 12px; + color: var(--main-color); + margin: 0; + padding: 1px 0 2px; + -webkit-padding-start: 4px; + padding-inline-start: 4px; + border: none; + background-color: var(--dropdown-btn-bg-color); +} +.dropdownToolbarButton > select:hover, +.dropdownToolbarButton > select:focus-visible { + background-color: var(--button-hover-color); + color: var(--toggled-btn-color); +} +.dropdownToolbarButton > select > option { + background: var(--doorhanger-bg-color); + color: var(--main-color); } -.toolbarButton.openFile::before { - content: url(images/toolbarButton-openFile.svg); - /*content: var(--toolbarButton-openFile-icon);*/ +.toolbarButtonSpacer { + width: 30px; + display: inline-block; + height: 1px; } -@media (prefers-color-scheme: dark) { +.toolbarButton::before, +.secondaryToolbarButton::before, +.dropdownToolbarButton::after, +.treeItemToggler::before { + /* All matching images have a size of 16x16 + * All relevant containers have a size of 28x28 */ + position: absolute; + display: inline-block; + width: 16px; + height: 16px; - .toolbarButton.openFile::before { - content: url(images/toolbarButton-openFile-dark.svg); - /*content: var(--toolbarButton-openFile-icon);*/ - } + content: ""; + background-color: var(--toolbar-icon-bg-color); + -webkit-mask-size: cover; + mask-size: cover; } -.secondaryToolbarButton.openFile::before { - content: url(images/toolbarButton-openFile.svg); - /*content: var(--toolbarButton-openFile-icon);*/ +.dropdownToolbarButton:hover::after, +.dropdownToolbarButton:focus-visible::after, +.dropdownToolbarButton:active::after { + background-color: var(--toolbar-icon-hover-bg-color); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.openFile::before { - content: url(images/toolbarButton-openFile-dark.svg); - /*content: var(--toolbarButton-openFile-icon);*/ - } +.toolbarButton::before { + opacity: var(--toolbar-icon-opacity); + top: 6px; + left: 6px; } -.toolbarButton.download::before { - content: url(images/toolbarButton-download.svg); - /*content: var(--toolbarButton-download-icon);*/ +.toolbarButton:hover::before, +.toolbarButton:focus-visible::before, +.secondaryToolbarButton:hover::before, +.secondaryToolbarButton:focus-visible::before { + background-color: var(--toolbar-icon-hover-bg-color); } -@media (prefers-color-scheme: dark) { - - .toolbarButton.download::before { - content: url(images/toolbarButton-download-dark.svg); - /*content: var(--toolbarButton-download-icon);*/ - } +[dir="ltr"] .secondaryToolbarButton::before { + left: 12px; } -.secondaryToolbarButton.download::before { - content: url(images/toolbarButton-download.svg); - /*content: var(--toolbarButton-download-icon);*/ +[dir="rtl"] .secondaryToolbarButton::before { + right: 12px; } -@media (prefers-color-scheme: dark) { +.secondaryToolbarButton::before { + opacity: var(--doorhanger-icon-opacity); + top: 5px; + inset-inline-start: 12px; +} - .secondaryToolbarButton.download::before { - content: url(images/toolbarButton-download-dark.svg); - /*content: var(--toolbarButton-download-icon);*/ - } +#sidebarToggle::before { + -webkit-mask-image: var(--toolbarButton-sidebarToggle-icon); + mask-image: var(--toolbarButton-sidebarToggle-icon); + transform: scaleX(var(--dir-factor)); } -.secondaryToolbarButton.bookmark { - padding-top: 6px; - text-decoration: none; +#secondaryToolbarToggle::before { + -webkit-mask-image: var(--toolbarButton-secondaryToolbarToggle-icon); + mask-image: var(--toolbarButton-secondaryToolbarToggle-icon); + transform: scaleX(var(--dir-factor)); } -.bookmark[href="#"] { - opacity: 0.5; - pointer-events: none; +#findPrevious::before { + -webkit-mask-image: var(--findbarButton-previous-icon); + mask-image: var(--findbarButton-previous-icon); } -.toolbarButton.bookmark::before { - content: url(images/toolbarButton-bookmark.svg); - /*content: var(--toolbarButton-bookmark-icon);*/ +#findNext::before { + -webkit-mask-image: var(--findbarButton-next-icon); + mask-image: var(--findbarButton-next-icon); } -@media (prefers-color-scheme: dark) { +#previous::before { + -webkit-mask-image: var(--toolbarButton-pageUp-icon); + mask-image: var(--toolbarButton-pageUp-icon); +} - .toolbarButton.bookmark::before { - content: url(images/toolbarButton-bookmark-dark.svg); - /*content: var(--toolbarButton-bookmark-icon);*/ - } +#next::before { + -webkit-mask-image: var(--toolbarButton-pageDown-icon); + mask-image: var(--toolbarButton-pageDown-icon); } -.secondaryToolbarButton.bookmark::before { - content: url(images/toolbarButton-bookmark.svg); - /*content: var(--toolbarButton-bookmark-icon);*/ +#zoomOut::before { + -webkit-mask-image: var(--toolbarButton-zoomOut-icon); + mask-image: var(--toolbarButton-zoomOut-icon); } -@media (prefers-color-scheme: dark) { +#zoomIn::before { + -webkit-mask-image: var(--toolbarButton-zoomIn-icon); + mask-image: var(--toolbarButton-zoomIn-icon); +} - .secondaryToolbarButton.bookmark::before { - content: url(images/toolbarButton-bookmark-dark.svg); - /*content: var(--toolbarButton-bookmark-icon);*/ - } +#presentationMode::before, +#secondaryPresentationMode::before { + -webkit-mask-image: var(--toolbarButton-presentationMode-icon); + mask-image: var(--toolbarButton-presentationMode-icon); } -#viewThumbnail.toolbarButton::before { - content: url(images/toolbarButton-viewThumbnail.svg); - /*content: var(--toolbarButton-viewThumbnail-icon);*/ +#editorFreeText::before { + -webkit-mask-image: var(--toolbarButton-editorFreeText-icon); + mask-image: var(--toolbarButton-editorFreeText-icon); } -@media (prefers-color-scheme: dark) { +#editorInk::before { + -webkit-mask-image: var(--toolbarButton-editorInk-icon); + mask-image: var(--toolbarButton-editorInk-icon); +} - #viewThumbnail.toolbarButton::before { - content: url(images/toolbarButton-viewThumbnail-dark.svg); - /*content: var(--toolbarButton-viewThumbnail-icon);*/ - } +#print::before, +#secondaryPrint::before { + -webkit-mask-image: var(--toolbarButton-print-icon); + mask-image: var(--toolbarButton-print-icon); } -#viewOutline.toolbarButton::before { - content: url(images/toolbarButton-viewOutline.svg); - /*content: var(--toolbarButton-viewOutline-icon);*/ +#openFile::before, +#secondaryOpenFile::before { + -webkit-mask-image: var(--toolbarButton-openFile-icon); + mask-image: var(--toolbarButton-openFile-icon); } -@media (prefers-color-scheme: dark) { +#download::before, +#secondaryDownload::before { + -webkit-mask-image: var(--toolbarButton-download-icon); + mask-image: var(--toolbarButton-download-icon); +} - #viewOutline.toolbarButton::before { - content: url(images/toolbarButton-viewOutline-dark.svg); - /*content: var(--toolbarButton-viewOutline-icon);*/ - } +a.secondaryToolbarButton { + padding-top: 6px; + text-decoration: none; } -html[dir="rtl"] #viewOutline.toolbarButton::before { - transform: scaleX(-1); +a.toolbarButton[href="#"], +a.secondaryToolbarButton[href="#"] { + opacity: 0.5; + pointer-events: none; } -#viewAttachments.toolbarButton::before { - content: url(images/toolbarButton-viewAttachments.svg); - /*content: var(--toolbarButton-viewAttachments-icon);*/ +#viewBookmark::before, +#secondaryViewBookmark::before { + -webkit-mask-image: var(--toolbarButton-bookmark-icon); + mask-image: var(--toolbarButton-bookmark-icon); } -@media (prefers-color-scheme: dark) { +#viewThumbnail::before { + -webkit-mask-image: var(--toolbarButton-viewThumbnail-icon); + mask-image: var(--toolbarButton-viewThumbnail-icon); +} - #viewAttachments.toolbarButton::before { - content: url(images/toolbarButton-viewAttachments-dark.svg); - /*content: var(--toolbarButton-viewAttachments-icon);*/ - } +#viewOutline::before { + -webkit-mask-image: var(--toolbarButton-viewOutline-icon); + mask-image: var(--toolbarButton-viewOutline-icon); + transform: scaleX(var(--dir-factor)); } -#viewLayers.toolbarButton::before { - content: url(images/toolbarButton-viewLayers.svg); - /*content: var(--toolbarButton-viewLayers-icon);*/ +#viewAttachments::before { + -webkit-mask-image: var(--toolbarButton-viewAttachments-icon); + mask-image: var(--toolbarButton-viewAttachments-icon); } -@media (prefers-color-scheme: dark) { +#viewLayers::before { + -webkit-mask-image: var(--toolbarButton-viewLayers-icon); + mask-image: var(--toolbarButton-viewLayers-icon); +} - #viewLayers.toolbarButton::before { - content: url(images/toolbarButton-viewLayers-dark.svg); - /*content: var(--toolbarButton-viewLayers-icon);*/ - } +#currentOutlineItem::before { + -webkit-mask-image: var(--toolbarButton-currentOutlineItem-icon); + mask-image: var(--toolbarButton-currentOutlineItem-icon); + transform: scaleX(var(--dir-factor)); } -#viewFind.toolbarButton::before { - content: url(images/toolbarButton-search.svg); - /*content: var(--toolbarButton-search-icon);*/ +#viewFind::before { + -webkit-mask-image: var(--toolbarButton-search-icon); + mask-image: var(--toolbarButton-search-icon); } -@media (prefers-color-scheme: dark) { +[dir="ltr"] .pdfSidebarNotification::after { + left: 17px; +} - #viewFind.toolbarButton::before { - content: url(images/toolbarButton-search-dark.svg); - /*content: var(--toolbarButton-search-icon);*/ - } +[dir="rtl"] .pdfSidebarNotification::after { + right: 17px; } -.toolbarButton.pdfSidebarNotification::after { +.pdfSidebarNotification::after { position: absolute; display: inline-block; top: 1px; + inset-inline-start: 17px; /* Create a filled circle, with a diameter of 9 pixels, using only CSS: */ content: ""; background-color: rgba(112, 219, 85, 1); @@ -2794,333 +2304,177 @@ html[dir="rtl"] #viewOutline.toolbarButton::before { width: 9px; border-radius: 50%; } -html[dir="ltr"] .toolbarButton.pdfSidebarNotification::after { - left: 17px; -} -html[dir="rtl"] .toolbarButton.pdfSidebarNotification::after { - right: 17px; -} -.secondaryToolbarButton { - position: relative; - margin: 0; - padding: 0 0 1px 0; - height: auto; - min-height: 26px; - width: auto; - min-width: 100%; - white-space: normal; - border-radius: 0; - box-sizing: border-box; -} -html[dir="ltr"] .secondaryToolbarButton { +[dir="ltr"] .secondaryToolbarButton { padding-left: 36px; - text-align: left; -} -html[dir="rtl"] .secondaryToolbarButton { - padding-right: 36px; - text-align: right; -} - -html[dir="ltr"] .secondaryToolbarButton > span { - padding-right: 4px; -} -html[dir="rtl"] .secondaryToolbarButton > span { - padding-left: 4px; -} - -.secondaryToolbarButton.firstPage::before { - content: url(images/secondaryToolbarButton-firstPage.svg); - /*content: var(--secondaryToolbarButton-firstPage-icon);*/ -} - -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.firstPage::before { - content: url(images/secondaryToolbarButton-firstPage-dark.svg); - /*content: var(--secondaryToolbarButton-firstPage-icon);*/ - } -} - -.secondaryToolbarButton.lastPage::before { - content: url(images/secondaryToolbarButton-lastPage.svg); - /*content: var(--secondaryToolbarButton-lastPage-icon);*/ -} - -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.lastPage::before { - content: url(images/secondaryToolbarButton-lastPage-dark.svg); - /*content: var(--secondaryToolbarButton-lastPage-icon);*/ - } -} - -.secondaryToolbarButton.rotateCcw::before { - content: url(images/secondaryToolbarButton-rotateCcw.svg); - /*content: var(--secondaryToolbarButton-rotateCcw-icon);*/ } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.rotateCcw::before { - content: url(images/secondaryToolbarButton-rotateCcw-dark.svg); - /*content: var(--secondaryToolbarButton-rotateCcw-icon);*/ - } +[dir="rtl"] .secondaryToolbarButton { + padding-right: 36px; } -.secondaryToolbarButton.rotateCw::before { - content: url(images/secondaryToolbarButton-rotateCw.svg); - /*content: var(--secondaryToolbarButton-rotateCw-icon);*/ +[dir="ltr"] .secondaryToolbarButton { + text-align: left; } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.rotateCw::before { - content: url(images/secondaryToolbarButton-rotateCw-dark.svg); - /*content: var(--secondaryToolbarButton-rotateCw-icon);*/ - } +[dir="rtl"] .secondaryToolbarButton { + text-align: right; } -.secondaryToolbarButton.selectTool::before { - content: url(images/secondaryToolbarButton-selectTool.svg); - /*content: var(--secondaryToolbarButton-selectTool-icon);*/ +.secondaryToolbarButton { + position: relative; + margin: 0; + padding: 0 0 1px; + -webkit-padding-start: 36px; + padding-inline-start: 36px; + height: auto; + min-height: 26px; + width: auto; + min-width: 100%; + text-align: start; + white-space: normal; + border-radius: 0; + box-sizing: border-box; } - -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.selectTool::before { - content: url(images/secondaryToolbarButton-selectTool-dark.svg); - /*content: var(--secondaryToolbarButton-selectTool-icon);*/ - } +[dir="ltr"] .secondaryToolbarButton > span { + padding-right: 4px; } - -.secondaryToolbarButton.handTool::before { - content: url(images/secondaryToolbarButton-handTool.svg); - /*content: var(--secondaryToolbarButton-handTool-icon);*/ +[dir="rtl"] .secondaryToolbarButton > span { + padding-left: 4px; } - -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.handTool::before { - content: url(images/secondaryToolbarButton-handTool-dark.svg); - /*content: var(--secondaryToolbarButton-handTool-icon);*/ - } +.secondaryToolbarButton > span { + -webkit-padding-end: 4px; + padding-inline-end: 4px; } -.secondaryToolbarButton.scrollVertical::before { - content: url(images/secondaryToolbarButton-scrollVertical.svg); - /*content: var(--secondaryToolbarButton-scrollVertical-icon);*/ +#firstPage::before { + -webkit-mask-image: var(--secondaryToolbarButton-firstPage-icon); + mask-image: var(--secondaryToolbarButton-firstPage-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.scrollVertical::before { - content: url(images/secondaryToolbarButton-scrollVertical-dark.svg); - /*content: var(--secondaryToolbarButton-scrollVertical-icon);*/ - } +#lastPage::before { + -webkit-mask-image: var(--secondaryToolbarButton-lastPage-icon); + mask-image: var(--secondaryToolbarButton-lastPage-icon); } -.secondaryToolbarButton.scrollHorizontal::before { - content: url(images/secondaryToolbarButton-scrollHorizontal.svg); - /*content: var(--secondaryToolbarButton-scrollHorizontal-icon);*/ +#pageRotateCcw::before { + -webkit-mask-image: var(--secondaryToolbarButton-rotateCcw-icon); + mask-image: var(--secondaryToolbarButton-rotateCcw-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.scrollHorizontal::before { - content: url(images/secondaryToolbarButton-scrollHorizontal-dark.svg); - /*content: var(--secondaryToolbarButton-scrollHorizontal-icon);*/ - } +#pageRotateCw::before { + -webkit-mask-image: var(--secondaryToolbarButton-rotateCw-icon); + mask-image: var(--secondaryToolbarButton-rotateCw-icon); } -.secondaryToolbarButton.scrollWrapped::before { - content: url(images/secondaryToolbarButton-scrollWrapped.svg); - /*content: var(--secondaryToolbarButton-scrollWrapped-icon);*/ +#cursorSelectTool::before { + -webkit-mask-image: var(--secondaryToolbarButton-selectTool-icon); + mask-image: var(--secondaryToolbarButton-selectTool-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.scrollWrapped::before { - content: url(images/secondaryToolbarButton-scrollWrapped-dark.svg); - /*content: var(--secondaryToolbarButton-scrollWrapped-icon);*/ - } +#cursorHandTool::before { + -webkit-mask-image: var(--secondaryToolbarButton-handTool-icon); + mask-image: var(--secondaryToolbarButton-handTool-icon); } -.secondaryToolbarButton.spreadNone::before { - content: url(images/secondaryToolbarButton-spreadNone.svg); - /*content: var(--secondaryToolbarButton-spreadNone-icon);*/ +#scrollPage::before { + -webkit-mask-image: var(--secondaryToolbarButton-scrollPage-icon); + mask-image: var(--secondaryToolbarButton-scrollPage-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.spreadNone::before { - content: url(images/secondaryToolbarButton-spreadNone-dark.svg); - /*content: var(--secondaryToolbarButton-spreadNone-icon);*/ - } +#scrollVertical::before { + -webkit-mask-image: var(--secondaryToolbarButton-scrollVertical-icon); + mask-image: var(--secondaryToolbarButton-scrollVertical-icon); } -.secondaryToolbarButton.spreadOdd::before { - content: url(images/secondaryToolbarButton-spreadOdd.svg); - /*content: var(--secondaryToolbarButton-spreadOdd-icon);*/ +#scrollHorizontal::before { + -webkit-mask-image: var(--secondaryToolbarButton-scrollHorizontal-icon); + mask-image: var(--secondaryToolbarButton-scrollHorizontal-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.spreadOdd::before { - content: url(images/secondaryToolbarButton-spreadOdd-dark.svg); - /*content: var(--secondaryToolbarButton-spreadOdd-icon);*/ - } +#scrollWrapped::before { + -webkit-mask-image: var(--secondaryToolbarButton-scrollWrapped-icon); + mask-image: var(--secondaryToolbarButton-scrollWrapped-icon); } -.secondaryToolbarButton.spreadEven::before { - content: url(images/secondaryToolbarButton-spreadEven.svg); - /*content: var(--secondaryToolbarButton-spreadEven-icon);*/ +#spreadNone::before { + -webkit-mask-image: var(--secondaryToolbarButton-spreadNone-icon); + mask-image: var(--secondaryToolbarButton-spreadNone-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.spreadEven::before { - content: url(images/secondaryToolbarButton-spreadEven-dark.svg); - /*content: var(--secondaryToolbarButton-spreadEven-icon);*/ - } +#spreadOdd::before { + -webkit-mask-image: var(--secondaryToolbarButton-spreadOdd-icon); + mask-image: var(--secondaryToolbarButton-spreadOdd-icon); } -.secondaryToolbarButton.documentProperties::before { - content: url(images/secondaryToolbarButton-documentProperties.svg); - /*content: var(--secondaryToolbarButton-documentProperties-icon);*/ +#spreadEven::before { + -webkit-mask-image: var(--secondaryToolbarButton-spreadEven-icon); + mask-image: var(--secondaryToolbarButton-spreadEven-icon); } -@media (prefers-color-scheme: dark) { - - .secondaryToolbarButton.documentProperties::before { - content: url(images/secondaryToolbarButton-documentProperties-dark.svg); - /*content: var(--secondaryToolbarButton-documentProperties-icon);*/ - } +#documentProperties::before { + -webkit-mask-image: var(--secondaryToolbarButton-documentProperties-icon); + mask-image: var(--secondaryToolbarButton-documentProperties-icon); } .verticalToolbarSeparator { display: block; - padding: 11px 0; margin: 5px 2px; width: 1px; - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--separator-color); -} - -@media (prefers-color-scheme: dark) { - - .verticalToolbarSeparator { - background-color: rgba(0, 0, 0, 0.3); + height: 22px; background-color: var(--separator-color); - } -} -html[dir="ltr"] .verticalToolbarSeparator { - margin-left: 2px; } -html[dir="rtl"] .verticalToolbarSeparator { - margin-right: 2px; -} - .horizontalToolbarSeparator { display: block; - margin: 6px 0 5px 0; + margin: 6px 0; height: 1px; width: 100%; - border-top: 1px solid rgba(222, 222, 222, 1); - border-top: 1px solid var(--doorhanger-separator-color); -} - -@media (prefers-color-scheme: dark) { - - .horizontalToolbarSeparator { - border-top: 1px solid rgba(92, 92, 97, 1); - border-top: 1px solid var(--doorhanger-separator-color); - } + background-color: var(--doorhanger-separator-color); } .toolbarField { padding: 4px 7px; - margin: 3px 0 3px 0; + margin: 3px 0; border-radius: 2px; - background-color: rgba(255, 255, 255, 1); background-color: var(--field-bg-color); background-clip: padding-box; - border-width: 1px; - border-style: solid; - border-color: rgba(187, 187, 188, 1); - border-color: var(--field-border-color); + border: 1px solid var(--field-border-color); box-shadow: none; - color: rgba(6, 6, 6, 1); color: var(--field-color); font-size: 12px; line-height: 16px; outline-style: none; } -@media (prefers-color-scheme: dark) { - - .toolbarField { - color: rgba(250, 250, 250, 1); - color: var(--field-color); - } -} - -@media (prefers-color-scheme: dark) { - - .toolbarField { - border-color: rgba(115, 115, 115, 1); - border-color: var(--field-border-color); - } +[dir="ltr"] .toolbarField[type="checkbox"] { + margin-left: 7px; } -@media (prefers-color-scheme: dark) { - - .toolbarField { - background-color: rgba(64, 64, 68, 1); - background-color: var(--field-bg-color); - } +[dir="rtl"] .toolbarField[type="checkbox"] { + margin-right: 7px; } .toolbarField[type="checkbox"] { opacity: 0; position: absolute !important; left: 0; + margin: 10px 0 3px; + -webkit-margin-start: 7px; + margin-inline-start: 7px; } -html[dir="ltr"] .toolbarField[type="checkbox"] { - margin: 10px 0 3px 7px; -} - -html[dir="rtl"] .toolbarField[type="checkbox"] { - margin: 10px 7px 3px 0; -} - -.toolbarField.pageNumber { +#pageNumber { -moz-appearance: textfield; /* hides the spinner in moz */ - min-width: 16px; text-align: right; width: 40px; } - -.toolbarField.pageNumber.visiblePageIsLoading { - background-image: url(images/loading.svg); - /*background-image: var(--loading-icon);*/ +#pageNumber.visiblePageIsLoading { + background-image: var(--loading-icon); background-repeat: no-repeat; background-position: 3px; } - -@media (prefers-color-scheme: dark) { - - .toolbarField.pageNumber.visiblePageIsLoading { - background-image: url(images/loading-dark.svg); - /*background-image: var(--loading-icon);*/ - } -} - -.toolbarField.pageNumber::-webkit-inner-spin-button, -.toolbarField.pageNumber::-webkit-outer-spin-button { +#pageNumber::-webkit-inner-spin-button { -webkit-appearance: none; - margin: 0; } .toolbarField:focus { @@ -3129,45 +2483,49 @@ html[dir="rtl"] .toolbarField[type="checkbox"] { .toolbarLabel { min-width: 16px; - padding: 6px; + padding: 7px; margin: 2px; - border: 1px solid rgba(0, 0, 0, 0); border-radius: 2px; - color: rgba(12, 12, 13, 1); color: var(--main-color); font-size: 12px; line-height: 14px; text-align: left; -webkit-user-select: none; -moz-user-select: none; - -ms-user-select: none; user-select: none; cursor: default; } -@media (prefers-color-scheme: dark) { - - .toolbarLabel { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +[dir="ltr"] #numPages.toolbarLabel { + padding-left: 3px; } -html[dir="ltr"] #numPages.toolbarLabel { - padding-left: 2px; +[dir="rtl"] #numPages.toolbarLabel { + padding-right: 3px; } -html[dir="rtl"] #numPages.toolbarLabel { - padding-right: 2px; + +#numPages.toolbarLabel { + -webkit-padding-start: 3px; + padding-inline-start: 3px; } -#thumbnailView { +#thumbnailView, +#outlineView, +#attachmentsView, +#layersView { position: absolute; - width: calc(100% - 60px); + width: calc(100% - 8px); top: 0; bottom: 0; - padding: 10px 30px 0; + padding: 4px 4px 0; overflow: auto; - -webkit-overflow-scrolling: touch; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} +#thumbnailView { + width: calc(100% - 60px); + padding: 10px 30px 0; } #thumbnailView > a:active, @@ -3175,27 +2533,29 @@ html[dir="rtl"] #numPages.toolbarLabel { outline: 0; } -.thumbnail { - margin: 0 10px 5px 10px; -} -html[dir="ltr"] .thumbnail { +[dir="ltr"] .thumbnail { float: left; } -html[dir="rtl"] .thumbnail { + +[dir="rtl"] .thumbnail { float: right; } +.thumbnail { + float: inline-start; + margin: 0 10px 5px; +} + #thumbnailView > a:last-of-type > .thumbnail { margin-bottom: 10px; } - #thumbnailView > a:last-of-type > .thumbnail:not([data-loaded]) { margin-bottom: 9px; } .thumbnail:not([data-loaded]) { border: 1px dashed rgba(132, 132, 132, 1); - margin: -1px 9px 4px 9px; + margin: -1px 9px 4px; } .thumbnailImage { @@ -3217,306 +2577,140 @@ a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage, opacity: 0.9; } -a:focus > .thumbnail > .thumbnailSelectionRing { - background-color: rgba(0, 0, 0, 0.15); - background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - color: rgba(255, 255, 255, 0.9); -} - -@media (prefers-color-scheme: dark) { - - a:focus > .thumbnail > .thumbnailSelectionRing { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } -} - +a:focus > .thumbnail > .thumbnailSelectionRing, .thumbnail:hover > .thumbnailSelectionRing { - background-color: rgba(0, 0, 0, 0.15); - background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - color: rgba(255, 255, 255, 0.9); -} - -@media (prefers-color-scheme: dark) { - - .thumbnail:hover > .thumbnailSelectionRing { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } -} - -.thumbnail.selected > .thumbnailSelectionRing > .thumbnailImage { - opacity: 1; -} - -.thumbnail.selected > .thumbnailSelectionRing { - background-color: rgba(0, 0, 0, 0.15); - background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - color: rgba(255, 255, 255, 1); -} - -@media (prefers-color-scheme: dark) { - - .thumbnail.selected > .thumbnailSelectionRing { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } -} - -#outlineView, -#attachmentsView, -#layersView { - position: absolute; - width: calc(100% - 8px); - top: 0; - bottom: 0; - padding: 4px 4px 0; - overflow: auto; - -webkit-overflow-scrolling: touch; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -html[dir="ltr"] .treeWithDeepNesting > .treeItem, -html[dir="ltr"] .treeItem > .treeItems { - margin-left: 20px; -} - -html[dir="rtl"] .treeWithDeepNesting > .treeItem, -html[dir="rtl"] .treeItem > .treeItems { - margin-right: 20px; -} - -.treeItem > a { - text-decoration: none; - display: inline-block; - min-width: 95%; - /* Subtract the right padding (left, in RTL mode) of the container: */ - min-width: calc(100% - 4px); - height: auto; - margin-bottom: 1px; - border-radius: 2px; - color: rgba(0, 0, 0, 0.8); - color: var(--outline-color); - font-size: 13px; - line-height: 15px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - white-space: normal; - cursor: pointer; -} - -@media (prefers-color-scheme: dark) { - - .treeItem > a { - color: rgba(255, 255, 255, 0.8); - color: var(--outline-color); - } -} -html[dir="ltr"] .treeItem > a { - padding: 2px 0 5px 4px; -} -html[dir="rtl"] .treeItem > a { - padding: 2px 4px 5px 0; -} - -#layersView .treeItem > a > * { - cursor: pointer; -} -html[dir="ltr"] #layersView .treeItem > a > label { - padding-left: 4px; -} -html[dir="rtl"] #layersView .treesItem > a > label { - padding-right: 4px; -} - -.treeItemToggler { - position: relative; - height: 0; - width: 0; - color: rgba(255, 255, 255, 0.5); -} -.treeItemToggler::before { - content: url(images/treeitem-expanded.svg); - /*content: var(--treeitem-expanded-icon);*/ - display: inline-block; - position: absolute; - max-width: 16px; -} -@media (prefers-color-scheme: dark) { - - .treeItemToggler::before { - content: url(images/treeitem-expanded-dark.svg); - /*content: var(--treeitem-expanded-icon);*/ - } -} -.treeItemToggler.treeItemsHidden::before { - content: url(images/treeitem-collapsed.svg); - /*content: var(--treeitem-collapsed-icon);*/ - max-width: 16px; -} -@media (prefers-color-scheme: dark) { - - .treeItemToggler.treeItemsHidden::before { - content: url(images/treeitem-collapsed-dark.svg); - /*content: var(--treeitem-collapsed-icon);*/ - } -} -html[dir="rtl"] .treeItemToggler.treeItemsHidden::before { - transform: scaleX(-1); -} -.treeItemToggler.treeItemsHidden ~ .treeItems { - display: none; -} -html[dir="ltr"] .treeItemToggler { - float: left; -} -html[dir="rtl"] .treeItemToggler { - float: right; -} -html[dir="ltr"] .treeItemToggler::before { - right: 4px; -} -html[dir="rtl"] .treeItemToggler::before { - left: 4px; -} - -.treeItemToggler:hover { - background-color: rgba(0, 0, 0, 0.15); - background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - border-radius: 2px; - color: rgba(0, 0, 0, 0.9); - color: var(--outline-hover-color); -} - -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover { - color: rgba(255, 255, 255, 0.9); - color: var(--outline-hover-color); - } -} - -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } -} - -.treeItemToggler:hover + a { - background-color: rgba(0, 0, 0, 0.15); background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - border-radius: 2px; - color: rgba(0, 0, 0, 0.9); - color: var(--outline-hover-color); -} - -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover + a { + background-clip: padding-box; color: rgba(255, 255, 255, 0.9); - color: var(--outline-hover-color); - } } -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover + a { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } +.thumbnail.selected > .thumbnailSelectionRing > .thumbnailImage { + opacity: 1; } -.treeItemToggler:hover ~ .treeItems { - background-color: rgba(0, 0, 0, 0.15); +.thumbnail.selected > .thumbnailSelectionRing { background-color: var(--sidebaritem-bg-color); background-clip: padding-box; - border-radius: 2px; - color: rgba(0, 0, 0, 0.9); - color: var(--outline-hover-color); + color: rgba(255, 255, 255, 1); } -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover ~ .treeItems { - color: rgba(255, 255, 255, 0.9); - color: var(--outline-hover-color); - } +[dir="ltr"] .treeWithDeepNesting > .treeItem,[dir="ltr"] +.treeItem > .treeItems { + margin-left: 20px; } -@media (prefers-color-scheme: dark) { - - .treeItemToggler:hover ~ .treeItems { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } +[dir="rtl"] .treeWithDeepNesting > .treeItem,[dir="rtl"] +.treeItem > .treeItems { + margin-right: 20px; } -.treeItem > a:hover { - background-color: rgba(0, 0, 0, 0.15); - background-color: var(--sidebaritem-bg-color); - background-clip: padding-box; - border-radius: 2px; - color: rgba(0, 0, 0, 0.9); - color: var(--outline-hover-color); +.treeWithDeepNesting > .treeItem, +.treeItem > .treeItems { + -webkit-margin-start: 20px; + margin-inline-start: 20px; } -@media (prefers-color-scheme: dark) { - - .treeItem > a:hover { - color: rgba(255, 255, 255, 0.9); - color: var(--outline-hover-color); - } +[dir="ltr"] .treeItem > a { + padding-left: 4px; } -@media (prefers-color-scheme: dark) { +[dir="rtl"] .treeItem > a { + padding-right: 4px; +} - .treeItem > a:hover { - background-color: rgba(255, 255, 255, 0.15); - background-color: var(--sidebaritem-bg-color); - } +.treeItem > a { + text-decoration: none; + display: inline-block; + /* Subtract the right padding (left, in RTL mode) of the container: */ + min-width: calc(100% - 4px); + height: auto; + margin-bottom: 1px; + padding: 2px 0 5px; + -webkit-padding-start: 4px; + padding-inline-start: 4px; + border-radius: 2px; + color: var(--treeitem-color); + font-size: 13px; + line-height: 15px; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + white-space: normal; + cursor: pointer; } -.treeItem.selected { - background-color: rgba(0, 0, 0, 1); - background-color: var(--outline-active-bg-color); - background-clip: padding-box; - color: rgba(0, 0, 0, 0.08); - color: var(--outline-active-color); +#layersView .treeItem > a * { + cursor: pointer; +} +[dir="ltr"] #layersView .treeItem > a > label { + padding-left: 4px; +} +[dir="rtl"] #layersView .treeItem > a > label { + padding-right: 4px; +} +#layersView .treeItem > a > label { + -webkit-padding-start: 4px; + padding-inline-start: 4px; +} +[dir="ltr"] #layersView .treeItem > a > label > input { + float: left; +} +[dir="rtl"] #layersView .treeItem > a > label > input { + float: right; +} +#layersView .treeItem > a > label > input { + float: inline-start; + margin-top: 1px; } -@media (prefers-color-scheme: dark) { +[dir="ltr"] .treeItemToggler { + float: left; +} - .treeItem.selected { - color: rgba(255, 255, 255, 0.08); - color: var(--outline-active-color); - } +[dir="rtl"] .treeItemToggler { + float: right; } -@media (prefers-color-scheme: dark) { +.treeItemToggler { + position: relative; + float: inline-start; + height: 0; + width: 0; + color: rgba(255, 255, 255, 0.5); +} +[dir="ltr"] .treeItemToggler::before { + right: 4px; +} +[dir="rtl"] .treeItemToggler::before { + left: 4px; +} +.treeItemToggler::before { + inset-inline-end: 4px; + -webkit-mask-image: var(--treeitem-expanded-icon); + mask-image: var(--treeitem-expanded-icon); +} +.treeItemToggler.treeItemsHidden::before { + -webkit-mask-image: var(--treeitem-collapsed-icon); + mask-image: var(--treeitem-collapsed-icon); + transform: scaleX(var(--dir-factor)); +} +.treeItemToggler.treeItemsHidden ~ .treeItems { + display: none; +} - .treeItem.selected { - background-color: rgba(255, 255, 255, 1); - background-color: var(--outline-active-bg-color); - } +.treeItem.selected > a { + background-color: var(--treeitem-selected-bg-color); + color: var(--treeitem-selected-color); } -.noResults { - font-size: 12px; - color: rgba(255, 255, 255, 0.8); - font-style: italic; - cursor: default; +.treeItemToggler:hover, +.treeItemToggler:hover + a, +.treeItemToggler:hover ~ .treeItems, +.treeItem > a:hover { + background-color: var(--sidebaritem-bg-color); + background-clip: padding-box; + border-radius: 2px; + color: var(--treeitem-hover-color); } /* TODO: file FF bug to support ::-moz-selection:window-inactive @@ -3530,9 +2724,7 @@ html[dir="rtl"] .treeItemToggler::before { } #errorWrapper { - background: none repeat scroll 0 0 rgba(255, 74, 74, 1); - background: none repeat scroll 0 0 var(--errorWrapper-bg-color); - color: rgba(12, 12, 13, 1); + background-color: var(--errorWrapper-bg-color); color: var(--main-color); left: 0; position: absolute; @@ -3541,289 +2733,115 @@ html[dir="rtl"] .treeItemToggler::before { padding: 3px 6px; } -@media (prefers-color-scheme: dark) { - - #errorWrapper { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } -} - -@media (prefers-color-scheme: dark) { - - #errorWrapper { - background: none repeat scroll 0 0 rgba(199, 17, 17, 1); - background: none repeat scroll 0 0 var(--errorWrapper-bg-color); - } -} -.loadingInProgress #errorWrapper { - top: 37px; -} - #errorMessageLeft { float: left; } - #errorMessageRight { float: right; } +#errorSpacer { + clear: both; +} #errorMoreInfo { - background-color: rgba(255, 255, 255, 1); background-color: var(--field-bg-color); - color: rgba(6, 6, 6, 1); color: var(--field-color); - border: 1px solid rgba(187, 187, 188, 1); border: 1px solid var(--field-border-color); padding: 3px; margin: 3px; width: 98%; } -@media (prefers-color-scheme: dark) { - - #errorMoreInfo { - border: 1px solid rgba(115, 115, 115, 1); - border: 1px solid var(--field-border-color); - } -} - -@media (prefers-color-scheme: dark) { - - #errorMoreInfo { - color: rgba(250, 250, 250, 1); - color: var(--field-color); - } -} - -@media (prefers-color-scheme: dark) { - - #errorMoreInfo { - background-color: rgba(64, 64, 68, 1); - background-color: var(--field-bg-color); - } -} - -.overlayButton { +.dialogButton { width: auto; - margin: 3px 4px 2px 4px !important; - padding: 2px 11px 2px 11px; -} - -#overlayContainer { - display: table; - position: absolute; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.2); - z-index: 40000; -} -#overlayContainer > * { - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -#overlayContainer > .container { - display: table-cell; - vertical-align: middle; - text-align: center; + margin: 3px 4px 2px !important; + padding: 2px 11px; + color: var(--main-color); + background-color: var(--dialog-button-bg-color); + border: var(--dialog-button-border) !important; } -#overlayContainer > .container > .dialog { - display: inline-block; +dialog { + margin: auto; padding: 15px; border-spacing: 4px; - color: rgba(12, 12, 13, 1); color: var(--main-color); font-size: 12px; line-height: 14px; - background-color: rgba(255, 255, 255, 1); background-color: var(--doorhanger-bg-color); border: 1px solid rgba(0, 0, 0, 0.5); border-radius: 4px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); } - -@media (prefers-color-scheme: dark) { - - #overlayContainer > .container > .dialog { - background-color: rgba(74, 74, 79, 1); - background-color: var(--doorhanger-bg-color); - } +dialog::-webkit-backdrop { + background-color: rgba(0, 0, 0, 0.2); } - -@media (prefers-color-scheme: dark) { - - #overlayContainer > .container > .dialog { - color: rgba(249, 249, 250, 1); - color: var(--main-color); - } +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.2); } -.dialog > .row { +dialog > .row { display: table-row; } -.dialog > .row > * { +dialog > .row > * { display: table-cell; } -.dialog .toolbarField { +dialog .toolbarField { margin: 5px 0; } -.dialog .separator { +dialog .separator { display: block; - margin: 4px 0 4px 0; + margin: 4px 0; height: 1px; width: 100%; - background-color: rgba(0, 0, 0, 0.3); - background-color: var(--separator-color); -} - -@media (prefers-color-scheme: dark) { - - .dialog .separator { - background-color: rgba(0, 0, 0, 0.3); background-color: var(--separator-color); - } } -.dialog .buttonRow { +dialog .buttonRow { text-align: center; vertical-align: middle; } -.dialog :link { +dialog :link { color: rgba(255, 255, 255, 1); } -#passwordOverlay > .dialog { +#passwordDialog { text-align: center; } -#passwordOverlay .toolbarField { +#passwordDialog .toolbarField { width: 200px; } -#documentPropertiesOverlay > .dialog { +#documentPropertiesDialog { text-align: left; } -#documentPropertiesOverlay .row > * { - min-width: 100px; -} -html[dir="ltr"] #documentPropertiesOverlay .row > * { +[dir="ltr"] #documentPropertiesDialog .row > * { text-align: left; } -html[dir="rtl"] #documentPropertiesOverlay .row > * { +[dir="rtl"] #documentPropertiesDialog .row > * { text-align: right; } -#documentPropertiesOverlay .row > span { +#documentPropertiesDialog .row > * { + min-width: 100px; + text-align: start; +} +#documentPropertiesDialog .row > span { width: 125px; word-wrap: break-word; } -#documentPropertiesOverlay .row > p { +#documentPropertiesDialog .row > p { max-width: 225px; word-wrap: break-word; } -#documentPropertiesOverlay .buttonRow { +#documentPropertiesDialog .buttonRow { margin-top: 10px; } -.clearBoth { - clear: both; -} - -.fileInput { - background: rgba(255, 255, 255, 1); - color: rgba(0, 0, 0, 1); - margin-top: 5px; - visibility: hidden; - position: fixed; - right: 0; - top: 0; -} - -#PDFBug { - background: none repeat scroll 0 0 rgba(255, 255, 255, 1); - border: 1px solid rgba(102, 102, 102, 1); - position: fixed; - top: 32px; - right: 0; - bottom: 0; - font-size: 10px; - padding: 0; - width: 300px; -} -#PDFBug .controls { - background: rgba(238, 238, 238, 1); - border-bottom: 1px solid rgba(102, 102, 102, 1); - padding: 3px; -} -#PDFBug .panels { - bottom: 0; - left: 0; - overflow: auto; - -webkit-overflow-scrolling: touch; - position: absolute; - right: 0; - top: 27px; -} -#PDFBug .panels > div { - padding: 5px; -} -#PDFBug button.active { - font-weight: bold; -} -.debuggerShowText { - background: none repeat scroll 0 0 rgba(255, 255, 0, 1); - color: rgba(0, 0, 255, 1); -} -.debuggerHideText:hover { - background: none repeat scroll 0 0 rgba(255, 255, 0, 1); -} -#PDFBug .stats { - font-family: courier; - font-size: 10px; - white-space: pre; -} -#PDFBug .stats .title { - font-weight: bold; -} -#PDFBug table { - font-size: 10px; -} - -#viewer.textLayer-visible .textLayer { - opacity: 1; -} - -#viewer.textLayer-visible .canvasWrapper { - background-color: rgba(128, 255, 128, 1); -} - -#viewer.textLayer-visible .canvasWrapper canvas { - mix-blend-mode: screen; -} - -#viewer.textLayer-visible .textLayer > span { - background-color: rgba(255, 255, 0, 0.1); - color: rgba(0, 0, 0, 1); - border: solid 1px rgba(255, 0, 0, 0.5); - box-sizing: border-box; -} - -#viewer.textLayer-hover .textLayer > span:hover { - background-color: rgba(255, 255, 255, 1); - color: rgba(0, 0, 0, 1); -} - -#viewer.textLayer-shadow .textLayer > span { - background-color: rgba(255, 255, 255, 0.6); - color: rgba(0, 0, 0, 1); -} - .grab-to-pan-grab { - cursor: url("images/grab.cur"), move !important; cursor: -webkit-grab !important; cursor: grab !important; } @@ -3833,7 +2851,6 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { } .grab-to-pan-grab:active, .grab-to-pan-grabbing { - cursor: url("images/grabbing.cur"), move !important; cursor: -webkit-grabbing !important; cursor: grabbing !important; position: fixed; @@ -3856,51 +2873,9 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { } @media print { - /* General rules for printing. */ body { background: rgba(0, 0, 0, 0) none; } - - /* Rules for browsers that don't support mozPrintCallback. */ - #sidebarContainer, - #secondaryToolbar, - .toolbar, - #loadingBox, - #errorWrapper, - .textLayer { - display: none; - } - #viewerContainer { - overflow: visible; - } - - #mainContainer, - #viewerContainer, - .page, - .page canvas { - position: static; - padding: 0; - margin: 0; - } - - .page { - float: left; - display: none; - border: none; - box-shadow: none; - background-clip: content-box; - background-color: rgba(255, 255, 255, 1); - } - - .page[data-loaded] { - display: block; - } - - .fileInput { - display: none; - } - - /* Rules for browsers that support PDF.js printing */ body[data-pdfjsprinting] #outerContainer { display: none; } @@ -3911,18 +2886,38 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { height: 100%; } /* wrapper around (scaled) print canvas elements */ - #printContainer > div { - position: relative; - top: 0; - left: 0; - width: 1px; - height: 1px; - overflow: visible; + #printContainer > .printedPage { + page-break-after: always; + page-break-inside: avoid; + + /* The wrapper always cover the whole page. */ + height: 100%; + width: 100%; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + #printContainer > .xfaPrintedPage .xfaPage { + position: absolute; + } + + #printContainer > .xfaPrintedPage { page-break-after: always; page-break-inside: avoid; + width: 100%; + height: 100%; + position: relative; } - #printContainer canvas, - #printContainer img { + + #printContainer > .printedPage canvas, + #printContainer > .printedPage img { + /* The intrinsic canvas / image size will make sure that we fit the page. */ + max-width: 100%; + max-height: 100%; + direction: ltr; display: block; } @@ -3945,28 +2940,21 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { } @media all and (max-width: 840px) { - #sidebarContent { - background-color: rgba(0, 0, 0, 0.7); - } - - html[dir="ltr"] #outerContainer.sidebarOpen #viewerContainer { - left: 0px !important; + #sidebarContainer { + background-color: var(--sidebar-narrow-bg-color); } - html[dir="rtl"] #outerContainer.sidebarOpen #viewerContainer { - right: 0px !important; + [dir="ltr"] #outerContainer.sidebarOpen #viewerContainer { + left: 0 !important; } - - #outerContainer .hiddenLargeView, - #outerContainer .hiddenMediumView { - display: inherit; + [dir="rtl"] #outerContainer.sidebarOpen #viewerContainer { + right: 0 !important; } - #outerContainer .visibleLargeView, - #outerContainer .visibleMediumView { - display: none; + #outerContainer.sidebarOpen #viewerContainer { + inset-inline-start: 0 !important; } } -@media all and (max-width: 770px) { +@media all and (max-width: 820px) { #outerContainer .hiddenLargeView { display: none; } @@ -3975,7 +2963,7 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { } } -@media all and (max-width: 700px) { +@media all and (max-width: 750px) { #outerContainer .hiddenMediumView { display: none; } @@ -3984,7 +2972,7 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { } } -@media all and (max-width: 640px) { +@media all and (max-width: 690px) { .hiddenSmallView, .hiddenSmallView * { display: none; @@ -3995,15 +2983,18 @@ html[dir="rtl"] #documentPropertiesOverlay .row > * { .toolbarButtonSpacer { width: 0; } - html[dir="ltr"] .findbar { + [dir="ltr"] .findbar { left: 34px; } - html[dir="rtl"] .findbar { + [dir="rtl"] .findbar { right: 34px; } + .findbar { + inset-inline-start: 34px; + } } -@media all and (max-width: 535px) { +@media all and (max-width: 560px) { #scaleSelectContainer { display: none; } diff --git a/cps/static/css/main.css b/cps/static/css/main.css index adbfbfdf..03cb0a01 100644 --- a/cps/static/css/main.css +++ b/cps/static/css/main.css @@ -567,6 +567,36 @@ input:-moz-placeholder { color: #454545; } font-size: 0.8em; } +.md-content .themes button { + display: inline-block; + border: none; + text-align: center; + text-decoration: none; + margin-top: 5%; + margin-right: 1%; + font-size: 16px; +} + +.md-content .themes button.darkTheme { + background-color: #202124; + color: white; +} + +.md-content .themes button.whiteTheme { + background-color: white; + color: black; +} + +.md-content .themes button.sepiaTheme { + background-color: #ece1ca; + color: black; +} + +.md-content .themes button.blackTheme { + background-color: black; + color: white; +} + /* Effect 1: Fade in and scale up */ .md-effect-1 .md-content { -webkit-transform: scale(0.7); 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 old mode 100644 new mode 100755 index f99779bd..909a3d22 --- 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 // /////////////////////////////// @@ -201,7 +195,7 @@ if ($("body.book").length > 0) { // Move dropdown lists higher in dom, replace bootstrap toggle with own toggle. $('ul[aria-labelledby="read-in-browser"]').insertBefore(".blur-wrapper").addClass("readinbrowser-drop"); - $('ul[aria-labelledby="send-to-kindle"]').insertBefore(".blur-wrapper").addClass("sendtokindle-drop"); + $('ul[aria-labelledby="send-to-kereader"]').insertBefore(".blur-wrapper").addClass("sendtoereader-drop"); $(".leramslist").insertBefore(".blur-wrapper"); $('ul[aria-labelledby="btnGroupDrop1"]').insertBefore(".blur-wrapper").addClass("leramslist"); $("#add-to-shelves").insertBefore(".blur-wrapper"); @@ -215,7 +209,7 @@ if ($("body.book").length > 0) { }); $("#sendbtn2").click(function () { - $(".sendtokindle-drop").toggle(); + $(".sendtoereader-drop").toggle(); }); @@ -242,12 +236,12 @@ if ($("body.book").length > 0) { if ($("#sendbtn2").length > 0) { position = $("#sendbtn2").offset().left - if (position + $(".sendtokindle-drop").width() > $(window).width()) { - positionOff = position + $(".sendtokindle-drop").width() - $(window).width(); + if (position + $(".sendtoereader-drop").width() > $(window).width()) { + positionOff = position + $(".sendtoereader-drop").width() - $(window).width(); ribPosition = position - positionOff - 5 - $(".sendtokindle-drop").attr("style", "left: " + ribPosition + "px !important; right: auto; top: " + topPos + "px"); + $(".sendtoereader-drop").attr("style", "left: " + ribPosition + "px !important; right: auto; top: " + topPos + "px"); } else { - $(".sendtokindle-drop").attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px"); + $(".sendtoereader-drop").attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px"); } } @@ -300,7 +294,7 @@ if ($("body.book").length > 0) { $(document).mouseup(function (e) { var container = new Array(); container.push($('ul[aria-labelledby="read-in-browser"]')); - container.push($(".sendtokindle-drop")); + container.push($(".sendtoereader-drop")); container.push($(".leramslist")); container.push($("#add-to-shelves")); container.push($(".navbar-collapse.collapse.in")); @@ -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 Kindle", + "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 268fe9ec..b7ed6c8b 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); @@ -163,23 +165,52 @@ kthoom.ImageFile = function(file) { this.mimeType = undefined; break; } + + // Reset mime type for special files originating from Apple devices + // This folder may contain files having image extensions (for example .jpg) but those files are not actual images + // Trying to view these files cause corrupted/empty pages in the comic reader and files should be ignored + if (this.filename.indexOf("__MACOSX") !== -1) { + this.mimeType = undefined; + } + if ( this.mimeType !== undefined) { this.dataURI = createURLFromArray(file.fileData, this.mimeType); } }; +function updateDirectionButtons(){ + var left = 1; + var 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 @@ -208,9 +239,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--; @@ -225,38 +261,49 @@ function loadFromArrayBuffer(ab) { } function scrollTocToActive() { - // Scroll to the thumbnail in the TOC on page change - $("#tocView").stop().animate({ - scrollTop: $("#tocView a.active").position().top - }, 200); -} - -function updatePage() { $(".page").text((currentImage + 1 ) + "/" + totalImages); // Mark the current page in the TOC $("#tocView a[data-page]") - // Remove the currently active thumbnail + // 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 + }, 200); +} + +function updatePage() { scrollTocToActive(); + scrollCurrentImageIntoView(); updateProgress(); + pageDisplayUpdate(); + setTheme(); - if (imageFiles[currentImage]) { - setImage(imageFiles[currentImage].dataURI); - } else { - setImage("loading"); - } + kthoom.setSettings(); + kthoom.saveSettings(); +} +function setTheme() { $("body").toggleClass("dark-theme", settings.theme === "dark"); $("#mainContent").toggleClass("disabled-scrollbar", settings.scrollbar === 0); +} - kthoom.setSettings(); - kthoom.saveSettings(); +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) { @@ -290,100 +337,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); + if ($("body").css("scrollHeight") / innerHeight > 1) { + $("body").css("overflowY", "scroll"); + } + + var img = new Image(); + img.onerror = function() { canvas.width = innerWidth - 100; - canvas.height = 200; + canvas.height = 300; x.fillStyle = "black"; - x.textAlign = "center"; - x.font = "24px sans-serif"; + x.font = "50px 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"); + 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; + } +} - 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; - } +// 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]); } } @@ -393,6 +433,7 @@ function showLeftPage() { } else { showNextPage(); } + setBookmark(); } function showRightPage() { @@ -401,6 +442,7 @@ function showRightPage() { } else { showPrevPage(); } + setBookmark(); } function showPrevPage() { @@ -410,10 +452,8 @@ function showPrevPage() { currentImage++; } else { updatePage(); - if (settings.nextPage === 0) { - $("#mainContent").scrollTop(0); - } } + updateDirectionButtons(); } function showNextPage() { @@ -423,36 +463,54 @@ function showNextPage() { currentImage--; } else { updatePage(); - if (settings.nextPage === 0) { - $("#mainContent").scrollTop(0); - } } + updateDirectionButtons(); } -function updateScale(clear) { - var mainImageStyle = getElem("mainImage").style; - mainImageStyle.width = ""; - mainImageStyle.height = ""; - mainImageStyle.maxWidth = ""; - mainImageStyle.maxHeight = ""; +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() { + var canvasArray = $("#mainContent > canvas"); var maxheight = innerHeight - 50; + + canvasArray.css("width", ""); + canvasArray.css("height", ""); + canvasArray.css("maxWidth", ""); + canvasArray.css("maxHeight", ""); + + if(settings.pageDisplay === 0) { + canvasArray.addClass("hide"); + pageDisplayUpdate(); + } - 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; - } + 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(); @@ -469,6 +527,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--; @@ -476,6 +548,7 @@ function keyHandler(evt) { settings.rotateTimes = 3; } updatePage(); + reloadImages(); break; case kthoom.Key.R: if (hasModifier) break; @@ -484,6 +557,7 @@ function keyHandler(evt) { settings.rotateTimes = 0; } updatePage(); + reloadImages(); break; case kthoom.Key.F: if (hasModifier) break; @@ -499,26 +573,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) { @@ -537,37 +612,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(); @@ -575,12 +698,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; @@ -588,33 +711,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"); @@ -625,16 +756,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(); @@ -668,5 +799,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 9ba173bb..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) %} - {{ book_checkbox_row('is_archived', _('Archiv Status'), false)}} + + {% 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 old mode 100644 new mode 100755 index 3af205fb..f28839f6 --- a/cps/templates/detail.html +++ b/cps/templates/detail.html @@ -1,325 +1,370 @@ {% 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 638b7245..3fa6958f 100644 --- a/cps/templates/grid.html +++ b/cps/templates/grid.html @@ -18,7 +18,7 @@

{{char.char}}
{% endfor %}
-
List
+
{{_('List')}}
{% if entries[0] %} @@ -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 8abd0c16..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,23 +86,32 @@ - -
{{_('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')}}
+
+
+ + + + + + + + + + - - - + @@ -126,68 +123,83 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + - + - - + + + + - - -
{{_('Settings')}}
{{_('Theme')}}: +
+ + +
+
{{_('Theme')}}:{{_('Display')}}:
- - + +
{{_('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 4bf025a3..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 62a29308..d41accc7 100644 --- a/cps/templates/stats.html +++ b/cps/templates/stats.html @@ -25,12 +25,12 @@ -{% 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')}}

-
{{_('Program Library')}}{{_('Program')}} {{_('Installed Version')}}
+
- {% 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 Kindle E-mail Address'), _('Kindle 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 - ) - 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") + 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)) + 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) + 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) - @staticmethod - def environ(request: httputil.HTTPServerRequest) -> Dict[Text, Any]: - environ = WSGIContainer.environ(request) + + def environ(self, request: httputil.HTTPServerRequest) -> Dict[Text, Any]: + try: + 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 0ae3a98a..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 9066dd54..0e02f429 100644 --- a/cps/translations/cs/LC_MESSAGES/messages.po +++ b/cps/translations/cs/LC_MESSAGES/messages.po @@ -6,604 +6,648 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n>=2 && n<=4 ? 1 : 2)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistika" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Úspěšně obnovené připojení" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Neznámý příkaz" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Stránka správce" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Základní konfigurace" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Konfigurace uživatelského rozhraní" -#: cps/admin.py:289 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:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Uživatel nenalezen" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfigurace Calibre-Web aktualizována" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Opravdu chcete odstranit Kobo token?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: 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:599 +#: 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:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Opravdu chcete vypnout?" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: 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:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Filtr objektů skupiny LDAP má nesrovnatelnou závorku" -#: cps/admin.py:1160 +#: 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:1162 +#: 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:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Chyba databáze: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "Databáze není zapisovatelná" - -#: cps/admin.py:1266 -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:1270 -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:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Nastavení e-mailového serveru aktualizováno" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Konfigurace funkcí" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Vyplňte všechna pole!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-mail není z platné domény" - -#: cps/admin.py:1416 cps/admin.py:1576 -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:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Uživatel '%(user)s' vytvořen" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Byl nalezen existující účet pro tuto e-mailovou adresu nebo přezdívku." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Uživatel '%(nick)s' smazán" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Změnit SMTP nastavení" -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Nezbývá žádný správce, nemůžete jej odstranit" - -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Upravit uživatele %(nick)s" - -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Uživatel '%(nick)s' aktualizován" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Neznámá chyba. Opakujte prosím později." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Změnit SMTP nastavení" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "" +msgid "Oops! Database Error: %(error)s." +msgstr "Chyba databáze: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Prvně nastavte svou e-mailovou adresu..." -#: cps/admin.py:1637 -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:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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 "Neznámá chyba. Opakujte prosím později." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Upravit uživatele %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Prohlížeč log souborů" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Požadování balíčku aktualizace" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Stahování balíčku aktualizace" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Rozbalování balíčku aktualizace" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Nahrazování souborů" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databázová připojení jsou uzavřena" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Zastavuji server" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Chyba připojení" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Všeobecná chyba" -#: cps/admin.py:1773 +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Chyba: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 -msgid "not installed" -msgstr "není nainstalováno" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Chybí povolení k exekuci" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Databáze není zapisovatelná" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Vlastní sloupec %(column)d neexistuje v databázi" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Žádné" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Formát knihy úspěšně smazán" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Kniha úspěšně smazána" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "Nastavení e-mailového serveru aktualizováno" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Konfigurace funkcí" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Jejda! Vybraná kniha není k dispozici. Soubor neexistuje nebo není přístupný" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Vyplňte všechna pole!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "upravit metadata" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-mail není z platné domény" -#: cps/editbooks.py:457 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Přidat nového uživatele" + +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +msgid "User '%(user)s' created" +msgstr "Uživatel '%(user)s' vytvořen" + +#: cps/admin.py:1926 +#, fuzzy +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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Uživatel '%(nick)s' smazán" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s není platným jazykem" +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Nezbývá žádný správce, nemůžete jej odstranit" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Uživatel '%(nick)s' aktualizován" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Soubor, který má být odeslán musí mít příponu" +#: cps/converter.py:31 +msgid "not installed" +msgstr "není nainstalováno" -#: cps/editbooks.py:655 -#, 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/converter.py:32 +msgid "Execution permissions missing" +msgstr "Chybí povolení k exekuci" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Uložení souboru %(file)s se nezdařilo." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Formát souboru %(ext)s přidán do %(book)s" +#: 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 "Žádné" + +#: 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:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata úspěšně aktualizována" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Soubor %(file)s nahrán" + +#: 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: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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Formát knihy úspěšně smazán" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Kniha úspěšně smazána" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "upravit metadata" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Soubor %(file)s nahrán" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Chybí zdrojový nebo cílový formát pro převod" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, 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" +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:1155 +#: cps/editbooks.py:1200 #, 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" +msgid "Failed to store file %(file)s." +msgstr "Uložení souboru %(file)s se nezdařilo." + +#: 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" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -618,187 +662,183 @@ msgstr "Doména zpětného volání není ověřena, postupujte podle pokynů k 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Poslat do Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Zkušební e-mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Začínáme s Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Poslat %(format)s do Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Poslat do Kindle" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Zadané uživatelské jméno je již použito" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Chyba stahování obalu" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Chyba formátu obalu" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Vytvoření cesty obalu selhalo" -#: cps/helper.py:799 +#: 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:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar binární soubor nenalezen" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Chyba provádění UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Čekám" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Selhalo" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Spuštěno" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Dokončeno" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Objevte" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Neznámý stav" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo nastavení" @@ -807,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:1613 +#: 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 @@ -868,12 +908,13 @@ msgstr "Google Oauth chyba, prosím opakujte později." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -889,497 +930,619 @@ 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Knihy" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Zobrazit nedávné knihy" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Zobrazit žhavé knihy" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Zobrazit nepřečtené" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Objevte" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Hodnocení" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Archivované knihy" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Hledat" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Vydáno po " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Vydáno před " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Hodnocení <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Hodnocení >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Rozšířené hledání" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Zadána neplatná police" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Lituji, nejste oprávněni přidat knihu do police: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Kniha je již součástí police: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Kniha byla přidána do police: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Knihy jsou již součástí police: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Knihy byly přidány do police: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Nelze přidat knihy do police: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Kniha byla odebrána z police: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Vytvořit polici" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Lituji, nejste oprávněni odebrat knihu z této police: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Upravit polici" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Kniha úspěšně smazána" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Změnit pořadí Police: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Police %(title)s vytvořena" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Police %(title)s změněna" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Došlo k chybě" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Kniha úspěšně smazána" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Změnit pořadí Police: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Police: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: 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 "Čekám" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Selhalo" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Spuštěno" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Dokončeno" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Neznámý 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 "Neočekávaná data při čtení informací o aktualizaci" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Aktualizace není k dispozici. Máte nainstalovanou nejnovější verzi" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Nová aktualizace k dispozici. Klepnutím na tlačítko níže aktualizujte na nejnovější verzi." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Nelze získat informace o aktualizaci" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Klepnutím na tlačítko níže aktualizujte na nejnovější stabilní verzi." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Nová aktualizace k dispozici. Klepnutím na tlačítko níže aktualizujte na verzi: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Nejsou k dispozici žádné informace o verzi" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Objevte (Náhodné knihy)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Žhavé knihy (Nejstahovanější)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autoři: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Vydavatel: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Série: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Hodnocení: %(rating)s stars" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Soubor formátů: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategorie: %(name)s" -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "Jazyky: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Rozšířené hledání" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Hledat" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Jazyky: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Stáhnutí" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Seznam hodnocení" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Seznam formátů" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Úlohy" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Vydáno po " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Vydáno před " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Hodnocení <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Hodnocení >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Nejprve nakonfigurujte nastavení pošty SMTP..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, 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" +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:1531 +#: 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 "Při odesílání této knihy došlo k chybě: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Nelze aktivovat ověření LDAP" -#: cps/web.py:1621 -#, 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:1627 -#, 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:1631 cps/web.py:1656 +#: 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:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Calibre převaděč %(tool)s nenalezen" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify-převaděč selhal: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Převedený soubor nebyl nalezen nebo více než jeden soubor ve složce %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Převaděč eknih selhal: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "upravit metadata" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Nahrávat" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Uživatelé" @@ -1392,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Poslat do Kindle e-mailová adresa" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Správce" @@ -1409,13 +1573,8 @@ msgstr "Správce" msgid "Password" msgstr "Heslo" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Nahrávat" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1429,7 +1588,7 @@ msgstr "Prohlížení knih" msgid "Edit" msgstr "Upravovat" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1440,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 @@ -1470,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 @@ -1542,78 +1697,109 @@ msgstr "Upravit základní konfiguraci" msgid "Edit UI Configuration" msgstr "Upravit konfiguraci uživatelského rozhraní" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Správa" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Zobrazit log" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Znovupřipojení ke Calibre databázi" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Restartovat" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Vypnout" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Aktualizovat" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Verze" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaily" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Současná verze" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Zkontrolovat aktualizace" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Provést aktualizaci" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Opravdu chcete restartovat?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Opravdu chcete vypnout?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Probíhá aktualizace, prosím nenačítejte stránku znovu" @@ -1625,39 +1811,39 @@ msgstr "přes" msgid "In Library" msgstr "V knihovně" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "redukovat" @@ -1665,165 +1851,166 @@ msgstr "redukovat" msgid "More by" msgstr "Více od" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Smazat knihu" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Smazat formáty:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Převést formát knihy:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Převést z:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "vyberte možnost" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Převést do:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Převést knihu" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Název knihy" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identifikátory" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Typy identifikátorů" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Hodnota identifikátorů" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Odstranit" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Přidat identifikátor" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Štítky" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID série" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Hodnocení" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Adresa URL obalu (jpg, obal je stažen a uložen v databázi, pole je potom opět prázdné)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Nahrát obal z místní jednotky" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Datum vydání" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Vydavatel" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Nahrát formát" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Zobrazit knihu po uložení" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Získat metadata" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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žit" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Klíčové slovo" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr "Hledat klíčové slovo" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Kliknutím na obal načtěte metadata do formuláře" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Načítání..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Zdroj" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Chyba vyhledávání!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Nebyly nalezeny žádné výsledky! Zadejte jiné klíčové slovo." @@ -1916,7 +2103,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1932,6 +2119,7 @@ msgid "Enter " msgstr "Identifikátory" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Jste si opravdu jisti?" @@ -2037,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 @@ -2053,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 @@ -2243,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" @@ -2255,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" @@ -2346,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Číst v prohližeči" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Poslechnout v prohlížeči" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publikováno" -#: cps/templates/detail.html:221 +#: 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:221 +#: 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:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Přečteno" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Obnovit z archivu" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Archívovat" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivováno" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Popis:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2442,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:29 +#: 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" @@ -2471,188 +2709,196 @@ 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:170 +#: 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 msgid "Kobo Token:" msgstr "Kobo Sync token" -#: cps/templates/http_error.html:31 +#: 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-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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Domů" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Přepnout navigaci" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Hledat v knihovně" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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ásit se" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Nahrávání..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Chyba" -#: cps/templates/layout.html:63 +#: 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:76 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 "Nastavení" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Účet" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Odhlásit se" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Prosím neobnovujte stránku" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Procházet" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "O knihovně" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Předchozí" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Podrobnosti o knize" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Zapamatovat si" @@ -2661,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" @@ -2757,7 +3003,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Kniha" @@ -2771,128 +3017,162 @@ msgstr "Calibre-Web katalog eknih" msgid "epub Reader" msgstr "Čtečka PDF" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Světlý" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Tmavý" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Zpět" + +#: 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:116 -msgid "Light" -msgstr "Světlý" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Tmavý" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Stránka správce" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2901,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" @@ -2920,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 @@ -2939,15 +3219,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Nenalezeny žádné výsledky" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Termín vyhledávání:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Výsledky pro:" @@ -2959,64 +3243,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Smazat tuto polici" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3061,8 +3353,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Knihovna programu" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3088,9 +3380,17 @@ 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 "" + +#: 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" @@ -3156,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Poslat do Kindle e-mailová adresa" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Zkušební e-mail" #: cps/templates/user_table.html:137 @@ -3236,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 9095d5bb..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 5aba0fe8..d6d9669d 100644 --- a/cps/translations/de/LC_MESSAGES/messages.po +++ b/cps/translations/de/LC_MESSAGES/messages.po @@ -7,593 +7,633 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+0200\n" -"PO-Revision-Date: 2022-01-10 17:37+0100\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" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistiken" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" -msgstr "Server neu gestartet, Seite bitte neu laden" - -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" -msgstr "Server wird heruntergefahren, Fenster bitte schließen" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." +msgstr "Server neu gestartet, Seite bitte neu laden." #: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "Erfolgreich neu verbunden" +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:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Unbekannter Befehl" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: 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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Admin Seite" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Basiskonfiguration" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Benutzeroberflächenkonfiguration" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Benutzer bearbeiten" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Benutzer nicht gefunden" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} Benutzer erfolgreich gelöscht" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Ungültige Anfrage" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Guest Benutzer kann diese Rolle nicht haben" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ungültige Rolle" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Guest Benutzer kann diese Sichtbarkeit nicht haben" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ungültige Sichtbarkeit" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Keine gültige Sprache gewählt" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Keine gültige Buchsprache gewählt" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter wurde nicht gefunden" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Ungültige Lese Spalte" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Ungültiger Spaltenname für Einschränkung" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfiguration von Calibre-Web wurde aktualisiert" -#: cps/admin.py:591 +#: 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:593 +#: 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:595 +#: 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:597 +#: 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:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Ort der Calibre Datenbank editieren?" -#: cps/admin.py:614 +#: 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: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:764 -msgid "Tag not found" -msgstr "Tag nicht gefunden" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Ungültige Aktion" - -#: cps/admin.py:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} Synchronisationseinträge gelöscht" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Tag nicht gefunden" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Ungültige Aktion" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Bitte einen LDAP Service Account eingeben" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Datenbankfehler: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "Datenbank ist nicht schreibbar" - -#: cps/admin.py:1266 -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:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "Zertifikatsdatei ist ungültig, bitte einen gültigen Pfad angeben" - -#: cps/admin.py:1378 -msgid "Database Settings updated" -msgstr "Datenbankeinstellung aktualisiert" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "Datenbank-Konfiguration" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Bitte alle Felder ausfüllen!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-Mail bezieht sich nicht auf eine gültige Domain" - -#: cps/admin.py:1416 cps/admin.py:1576 -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:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Benutzer '%(user)s' angelegt" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "Es existiert bereits ein Account für diese E-Mailadresse oder diesen Benutzernamen." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Benutzer '%(nick)s' gelöscht" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "Guest Benutzer kann nicht gelöscht werden" - -#: cps/admin.py:1469 -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:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "SMTP-Einstellungen ändern" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Benutzer %(nick)s bearbeiten" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "G-Mail Konto verifiziert." -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Benutzer '%(nick)s' aktualisiert" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "SMTP-Einstellungen ändern" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "Gmail Account Verifikation erfolgreich" +msgid "Oops! Database Error: %(error)s." +msgstr "Datenbankfehler: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Bitte zuerst E-Mail Adresse konfigurieren..." -#: cps/admin.py:1637 -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:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Einstellungen für Geplante Aufgaben" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Ungültigen Startzeitpunkt für Aufgaben spezifiziert" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Ungültige Laufzeit für Aufgaben spezifiziert" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Einstellungen für Geplante Aufgaben aktualisiert" + +#: 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:1394 +msgid "Settings DB is not Writeable" +msgstr "Einstellungsdatenbank ist nicht schreibbar" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Benutzer %(nick)s bearbeiten" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Logdatei Anzeige" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Frage Update an" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Lade Update herunter" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Entpacke Update" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Ersetze Dateien" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Schließe Datenbankverbindungen" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Stoppe Server" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Verbindungsfehler" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Timeout beim Verbindungsaufbau" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Allgemeiner Fehler" -#: cps/admin.py:1773 +#: 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:1774 +#: 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:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fehler: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Benutzer erfolgreich importiert" -#: cps/converter.py:30 -msgid "not installed" -msgstr "Nicht installiert" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Ausführeberechtigung fehlt" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Datenbank ist nicht schreibbar" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Benutzerdefinierte Spalte Nr. %(column)d ist nicht in Calibre Datenbank vorhanden" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Keine" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Buch Format erfolgreich gelöscht" +#: 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/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Buch erfolgreich gelöscht" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Datenbankeinstellung aktualisiert" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "Keine Erlaubnis zum Bücher löschen" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Datenbank-Konfiguration" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Öffnen des Buchs fehlgeschlagen. Datei existiert nicht oder ist nicht zugänglich" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Bitte alle Felder ausfüllen." -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "Metadaten editieren" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-Mail bezieht sich nicht auf eine gültige Domain" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s ist keine gültige Zahl, Eintrag wird ignoriert" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Neuen Benutzer hinzufügen" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1920 #, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "'%(langname)s' ist keine gültige Sprache" +msgid "User '%(user)s' created" +msgstr "Benutzer '%(user)s' angelegt" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" -msgstr "" +#: 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/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, 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" +msgid "User '%(nick)s' deleted" +msgstr "Benutzer '%(nick)s' gelöscht" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Dateien müssen eine Erweiterung haben, um hochgeladen zu werden" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Guest Benutzer kann nicht gelöscht werden" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Fehler beim Erzeugen des Pfads %(path)s (Zugriff verweigert)" +#: 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: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/editbooks.py:660 +#: cps/admin.py:2043 #, python-format -msgid "Failed to store file %(file)s." -msgstr "Fehler beim Speichern der Datei %(file)s." +msgid "User '%(nick)s' updated" +msgstr "Benutzer '%(nick)s' aktualisiert" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "Nicht installiert" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Ausführeberechtigung fehlt" -#: cps/editbooks.py:683 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Dateiformat %(ext)s zu %(book)s hinzugefügt" +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/editbooks.py:697 cps/editbooks.py:809 +#: 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 "Keine" + +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "Benutzer hat keine Berechtigung Cover hochzuladen" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadaten wurden erfolgreich aktualisiert" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "Fehler beim editieren des Buches: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Datei %(file)s hochgeladen" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Quell- oder Zielformat für Konvertierung fehlt" + +#: 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: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:951 +#: 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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Buch Format erfolgreich gelöscht" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Buch erfolgreich gelöscht" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Keine Erlaubnis zum Bücher löschen" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "Metadaten editieren" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Datei %(file)s hochgeladen" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s ist keine gültige Zahl, Eintrag wird ignoriert" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Quell- oder Zielformat für Konvertierung fehlt" +#: 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:1151 +#: cps/editbooks.py:1195 #, 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" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Fehler beim Erzeugen des Pfads %(path)s (Zugriff verweigert)" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Es trat ein Fehler beim Konvertieren des Buches auf: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Fehler beim Speichern der Datei %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Dateiformat %(ext)s zu %(book)s hinzugefügt" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -608,186 +648,176 @@ msgstr "Callback Domain ist nicht verifiziert, bitte Domain in der Google Develo 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" -msgstr "An Kindle senden" +#: 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:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" msgstr "Calibre-Web Test-E-Mail" -#: cps/helper.py:114 -msgid "Test e-mail" -msgstr "Test-E-Mail" +#: cps/helper.py:116 +msgid "Test Email" +msgstr "Test E-Mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Loslegen mit Calibre-Web" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" -msgstr "Konvertiere %(orig)s nach %(format)s und sende an Kindle" +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:172 cps/helper.py:176 cps/helper.py:180 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to Kindle" -msgstr "Sende %(format)s an Kindle" +msgid "Send %(format)s to eReader" +msgstr "Sende %(format)s an E-Reader" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to Kindle" -msgstr "%(book)s an Kindle senden" +msgid "%(book)s send to eReader" +msgstr "%(book)s an E-Reader gesendet" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "Gelesenen Status konnte nicht aktualisiert werden: {}" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 -#, fuzzy, python-format +#: cps/helper.py:447 +#, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" -msgstr "Umbenennen des Titels '%(src)s' zu '%(dest)s' schlug fehl: %(error)s" +msgstr "Umbenennen des Autors '%(src)s' zu '%(dest)s' schlug fehl: %(error)s" -#: cps/helper.py:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "Fehler beim umbenennen der Datei im Pfad: {}" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Benutzername ist schon vorhanden" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "Ungültiges E-Mail Adressformat" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" -msgstr "" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Fehler beim Herunterladen des Covers" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Coverdatei fehlerhaft" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" -msgstr "" +msgstr "Keine Berechtigung Cover von Localhost oder dem lokalen Netzwerk hochzuladen" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Fehler beim Erzeugen des Ordners für die Coverdatei" -#: cps/helper.py:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Ungültiger Cover Dateiinhalt" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "UnRar Programm nicht gefunden" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" -msgstr "Fehler beim ausführen von UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "Fehler beim Ausführen von UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Wartend" +#: cps/helper.py:1077 +msgid "Cover" +msgstr "Titelbild" -#: cps/helper.py:939 -msgid "Failed" -msgstr "Fehlgeschlagen" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Gestartet" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Alle Bücher für Metadaten Backup einreihen" -#: cps/helper.py:943 -msgid "Finished" -msgstr "Beendet" - -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Unbekannter Status" - -#: cps/kobo_auth.py:128 -#, fuzzy +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo Setup" @@ -796,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:1613 +#: 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 @@ -857,12 +887,13 @@ msgstr "Google Oauth Fehler, bitte später erneut versuchen." msgid "Google Oauth error: {}" msgstr "Google Oauth Fehler: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Sterne" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -878,495 +909,597 @@ msgstr "Token ist abgelaufen" msgid "Success! Please return to your device" msgstr "Erfolg! Bitte zum Gerät zurückkehren" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Bücher" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Zeige kürzlich hinzugefügte Bücher" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Zeige beliebte Bücher" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Heruntergeladene Bücher" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Zeige Ungelesene" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Entdecke" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Bewertungen" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Dateiformate" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Archivierte Bücher" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Bücherliste" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Suche" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Herausgegeben nach dem " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Herausgegeben vor dem " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Bewertung <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Bewertung >= %(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 "Fehler bei der Suche nach eigenen Spalten, bitte Calibre-Web neustarten" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Erweiterte Suche" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Ungültiges Bücherregal angegeben" -#: cps/shelf.py:73 +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Du hast keine Berechtigung, ein Buch zu diesem Bücherregal hinzuzufügen" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Buch ist bereits Teil des Bücherregals %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Das Buch wurde dem Bücherregal %(sname)s hinzugefügt" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "Keine Erlaubnis Bücher zu diesem Bücherregal hinzuzufügen" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Bücher sind bereits Teil des Bücherregals %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Bücher wurden zum Bücherregal %(sname)s hinzugefügt" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Bücher konnten nicht zum Bücherregal %(sname)s hinzugefügt werden" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Das Buch wurde aus dem Bücherregal: %(sname)s entfernt" -#: cps/shelf.py:218 +#: cps/shelf.py:200 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:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Bücherregal erzeugen" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" msgstr "Dir ist es nicht erlaubt, dieses Bücherregal zu editieren" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Bücherregal editieren" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Fehler beim Löschen des Bücherregals" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Bücherregal erfolgreich gelöscht" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Reihenfolge in Bücherregal '%(name)s' verändern" + +#: 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:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Bücherregal %(title)s erzeugt" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Bücherregal %(title)s verändert" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Es trat ein Fehler auf" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Buch erfolgreich gelöscht" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Reihenfolge in Bücherregal '%(name)s' verändern" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Bücherregal: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Aufgaben" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Wartend" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Fehlgeschlagen" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Gestartet" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Beendet" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Beendet" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Abgebrochen" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Unbekannter 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 "Updateinformationen enthalten unbekannte Daten" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Kein Update verfügbar. Es ist bereits die aktuellste Version installiert" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Es sind Updates verfügbar. Klicke auf den Button unten, um auf die aktuellste Version zu aktualisieren." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Updateinformationen konnten nicht geladen werden" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Klicke auf den Button unten, um auf die letzte stabile Version zu aktualisieren." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Ein neues Update ist verfügbar. Klicke auf den Button unten, um auf Version: %(version)s zu aktualisieren" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Keine Releaseinformationen verfügbar" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Entdecke (Zufällige Bücher)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Beliebte Bücher (am meisten Downloads)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Von %(user)s heruntergeladene Bücher" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Author: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Verleger: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serie: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Bewertung: Keine" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Bewertung: %(rating)s Sterne" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Dateiformat: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategorie: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Sprache: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Erweiterte Suche" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Suche" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Bewertungsliste" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Liste der Dateiformate" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Aufgaben" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Herausgegeben nach dem " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Herausgegeben vor dem " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Bewertung <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Bewertung >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Lesestatus = %(status)s" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "Fehler bei der Suche nach eigenen Spalten, bitte Calibre-Web neustarten" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "Bitte zuerst die SMTP-Einstellung konfigurieren..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Buch erfolgreich zum Senden an %(kindlemail)s eingereiht" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Buch erfolgreich zum Senden an %(eReadermail)s eingereiht" -#: cps/web.py:1531 +#: 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 "Beim Senden des Buchs trat ein Fehler auf: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Diese E-Mail ist nicht für die Registrierung zugelassen." -#: cps/web.py:1588 -msgid "Confirmation e-mail was send to your e-mail account." +#: 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:1602 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "LDAP-Authentifizierung kann nicht aktiviert werden" -#: cps/web.py:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "Login nicht erfolgreich: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "Falscher Benutzername oder Passwort" -#: cps/web.py:1638 +#: 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:1644 +#: 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:1651 +#: 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Calibre E-Book Konverter %(tool)s nicht gefunden" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s Format nicht gefunden" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "EBook Converter mit unbekanntem Fehler fehlgeschlagen" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify Konverter Aufruf fehlgeschlagen: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Konvertierte Datei nicht gefunden, oder mehr als eine Datei im Pfad %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Fehler des EBook-Converters: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre fehlgeschlagen mit Fehler: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Konvertiere" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Calibre Datenbank wird neu verbunden" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-Mail" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "Metadaten Backup läuft" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "%(count)s Cover Miniaturansichten erzeugt" + +#: 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:289 +msgid "Generated {0} series thumbnails" +msgstr "{0} Serien Miniaturansichten erzeugt" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Upload" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Benutzerliste" @@ -1379,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 Kindle E-mail Address" -msgstr "Kindle" +msgid "Send to eReader Email" +msgstr "An E-Reader E-Mail Adresse senden" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1396,13 +1529,8 @@ msgstr "Admin" msgid "Password" msgstr "Passwort" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Upload" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1416,7 +1544,7 @@ msgstr "Bücher ansehen" msgid "Edit" msgstr "Editieren" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1427,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 @@ -1457,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 @@ -1528,78 +1652,109 @@ msgstr "Basiskonfiguration" msgid "Edit UI Configuration" msgstr "Benutzeroberflächenkonfiguration" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Geplante Aufgabe" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: 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 Duration" +msgstr "Maximale Aufgabendauer" + +#: 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/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Mit Calibre Bibliothek neuverbinden" + +#: 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:203 msgid "Administration" msgstr "Administration" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Debug Daten herunterladen" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Logdateien ansehen" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Calibre-DB neu verbinden" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Neustart" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Calibre-Web beenden" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Update" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Versionsinformation" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Details" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Aktuelle Version" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Nach Update suchen" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Update durchführen" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Calibre-Web wirklich neustarten?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Calibre-Web wirklich anhalten?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Updatevorgang, Seite bitte nicht neu laden" @@ -1611,39 +1766,39 @@ msgstr "via" msgid "In Library" msgstr "In Bibliothek" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Sortiere nach Buchdatum, Neuestes zuerst" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Sortiere Titel in alphabetischer Reihenfolge" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Sortiere Titel in umgekehrt alphabetischer Reihenfolge" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Sortiere nach Herausgabedatum, Neueste zuerst" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Sortiere nach Herausgabedatum, Älteste zuerst" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "Reduzieren" @@ -1651,164 +1806,165 @@ msgstr "Reduzieren" msgid "More by" msgstr "Mehr von" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Buch löschen" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Lösche Formate:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Konvertiere Buchformat:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Konvertiere von:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "Wähle eine Option" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Konvertiere nach:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Konvertiere Buch" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Buchtitel" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Beschreibung" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "IDs" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "ID Typ" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "ID Wert" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Entfernen" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "ID hinzufügen" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tags" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "Serien ID" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Bewertung" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Cover-URL (jpg, Cover wird heruntergeladen und in der Datenbank gespeichert, Feld erscheint anschließend wieder leer)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Coverdatei von Lokalem Laufwerk hochladen" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Herausgabedatum" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Herausgeber" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Format hochladen" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Buch nach Bearbeitung ansehen" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Metadaten laden" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Speichern" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Suchbegriff" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 msgid "Search keyword" msgstr "Suche Schlüsselbegriff" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Klicke auf das Bild, um die Metadaten zu übertragen" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Lade..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Quelle" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Fehler bei der Suche!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Keine Ergebnisse gefunden! Bitte ein anderes Schlüsselwort benutzen." @@ -1900,8 +2056,8 @@ msgid "Comments" msgstr "Kommentare" #: cps/templates/book_table.html:75 -msgid "Archiv Status" -msgstr "" +msgid "Archive Status" +msgstr "Archivstatus" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" @@ -1915,6 +2071,7 @@ msgid "Enter " msgstr "Eingeben " #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Sicher?" @@ -2019,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 @@ -2035,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 @@ -2225,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" @@ -2237,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" @@ -2326,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Im Browser lesen" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Im Browser anhören" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Herausgabedatum" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Als ungelesen markieren" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Als gelesen markieren" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Gelesen" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Vom Archiv wiederherstellen" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Zum Archiv hinzufügen" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archiviert" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beschreibung:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2422,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:29 +#: 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" @@ -2451,187 +2654,194 @@ msgstr "Domainnamen eingeben" msgid "Denied Domains (Blacklist)" msgstr "Verbotene Domains für eine Registrierung" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 -#, fuzzy msgid "Kobo Token:" -msgstr "Kobo Sync Token" +msgstr "Kobo Token:" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Liste" + +#: 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" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "Aufsteigend nach Downloadzahlen sortieren" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "Absteigend nach Downloadzahlen sortieren" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Sortiere Autoren in alphabetischer Reihenfolge" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Sortiere Autoren in umgekehrt alphabetischer Reihenfolge" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Sortiere Serienindex aufsteigend" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Home" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Nagivation umschalten" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Bibiliothek durchsuchen" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Account" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Logout" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Lade hoch..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Fehler" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Hochladen beendet, verarbeite Daten, bitte warten..." -#: cps/templates/layout.html:76 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 "Einstellungen" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Account" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Logout" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Bitte die Seite nicht neu laden" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Durchsuchen" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Über" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Vorheriger Eintrag" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Buchdetails" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Raster" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Merken" @@ -2640,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" @@ -2736,7 +2946,7 @@ msgstr "Übergeordnetes Verzeichnis" msgid "Select" msgstr "Auswahl" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "Ok" @@ -2748,127 +2958,159 @@ msgstr "Calibre-Web E-Book-Katalog" msgid "epub Reader" msgstr "epub-Leser" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Hell" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Dunkel" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sepia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Schwarz" + +#: 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:116 -msgid "Light" -msgstr "Hell" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Darstellung" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Dunkel" +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "Einzelne Seite" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2876,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" @@ -2893,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 @@ -2912,15 +3154,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Thumbnails für Serien Cover erzeugen" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Keine Ergebnisse" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Suchbegriff:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Ergebnisse für:" @@ -2932,63 +3178,71 @@ 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:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Lösche dieses Bücherregal" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Bücherregal Eigenschaften bearbeiten" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Bücher manuell sortieren" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Manuelles Sortieren deaktivieren" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Manuelles Sortieren aktivieren" @@ -3033,8 +3287,8 @@ msgid "System Statistics" msgstr "System Statistiken" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Programm Bibliothek" +msgid "Program" +msgstr "Programm" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3060,9 +3314,17 @@ 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" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Diese Aufgabe wird abgebrochen. Der Fortschritt wird gespeichert." + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "Dies ist eine geplante Aufgabe, sie wird zur geplanten Zeit erneut ausgeführt." #: cps/templates/user_edit.html:20 msgid "Reset user Password" @@ -3125,16 +3387,16 @@ 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 Kindle E-mail Address" -msgstr "Kindle E-mail Adresse eingeben" +msgid "Enter eReader Email" +msgstr "E-Reader E-Mail Adresse eingeben" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "Kindle E-Mail" +msgid "eReader Email" +msgstr "E-Reader E-Mail" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3193,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 d61f1964..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 0a4b6419..4ebb35ba 100644 --- a/cps/translations/el/LC_MESSAGES/messages.po +++ b/cps/translations/el/LC_MESSAGES/messages.po @@ -6,604 +6,648 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Στατιστικά" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Ο διακομιστής επανεκκίνησε, παρακαλούμε φόρτωσε ξανά τη σελίδα" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Πραγματοποιείται κλείσιμο του διακομιστή, παρακαλούμε κλείσε το παράθυρο" -#: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "Επιτυχής επανασύνδεση" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Άγνωστη εντολή" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(eReadermail)s" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Σελίδα διαχειριστή" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Βασική Διαμόρφωση" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI Διαμόρφωση" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Χρήστης Διαχειριστής" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Όλα" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Δεν βρέθηκε χρήστης" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Δεν έχει απομείνει χρήστης διαχειριστής, δεν μπορεί να αφαιρεθεί ο ρόλος διαχειριστή" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Ενημερώθηκε η διαμόρφωση Calibre-Web" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Θέλεις πραγματικά να διαγράψεις τη Μονάδα Kobo;" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:599 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις κλείσιμο;" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json Δεν Έχει Διαμορφωθεί Για Διαδικτυακή Εφαρμογή" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Το Φύλλο Καταγραφής Τοποθεσίας δεν είναι Έγκυρο, Παρακαλούμε Συμπλήρωσε Τη Σωστή Πορεία" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Η Πρόσβαση Φύλλου Καταγραφης Τοποθεσίας δεν είναι έγκυρη, Παρακαλούμε Συμπλήρωσε Τη Σωστή Πορεία" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Παρακαλούμε Συμπλήρωσε ένα Πάροχο LDAP, Θύρα, DN και Αντικείμενο Αναγνώρισης Χρήστη" -#: cps/admin.py:1146 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Παρακαλούμε συμπλήρωσε ένα έγκυρο όνομα χρήστη για επαναφορά του κωδικού" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Το Αντικείμενο Φίλτρου Ομάδας LDAP Πρέπει να Έχει Μια \"%s\" Αναγνώριση Μορφής" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Το Αντικείμενο Φίλτρου Ομάδας LDAP Έχει Παρενθέσεις Που Δεν Ταιριάζουν" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Το Αντικείμενο Φίλτρου Χρήστη LDAP πρέπει να Έχει Μια \"%s\" Αναγνώριση Μορφής" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Το Αντικείμενο Φίλτρου Χρήστη LDAP Έχει Παρενθέσεις Που Δεν Ταιριάζουν" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Σφάλμα βάσης δεδομένων: %(error)s." - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "Η Τοποθεσία DB δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "Η DB δεν μπορεί να Γραφτεί" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "Το Αρχειο Κλειδί Τοποθεσίας δεν είναι Έγκυρο, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "Η Τοποθεσία Certfile δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Διαμόρφωση Λειτουργίας" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Παρακαλούμε συμπλήρωσε όλα τα πεδία!" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Προσθήκη Νέου Χρήστη" -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "Το E-mail δεν είναι από έγκυρο domain" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Επεξεργασία Ρυθμίσεων E-mail Διακομιστή" -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Προσθήκη νέου χρήστη" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" -msgstr "Χρήστης/ες '%(user)s' δημιουργήθηκαν" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Βρέθηκε ένας ήδη υπάρχον λογαριασμός για αυτή τη διεύθυνση e-mail ή όνομα χρήστη." +msgid "Oops! Database Error: %(error)s." +msgstr "Σφάλμα βάσης δεδομένων: %(error)s." -#: cps/admin.py:1463 +#: cps/admin.py:1323 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "Χρήστης/ες '%(nick)s' διαγράφηκαν" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Δεν έχει απομείνει χρήστης διαχειριστής, δεν μπορεί να διαγραφεί ο χρήστης" - -#: cps/admin.py:1542 cps/admin.py:1667 +#: cps/admin.py:1326 #, python-format -msgid "Edit User %(nick)s" -msgstr "Επεξεργασία χρήστη %(nick)s" +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Παρουσιάστηκε σφάλμα κατά την αποστολή του δοκιμαστικού e-mail:% (res)s" -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Χρήστης/ες '%(nick)s' ενημερώθηκαν" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Παρακαλούμε ρύθμισε πρώτα τη διεύθυνση e-mail σου..." -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Προέκυψε ένα άγνωστο σφάλμα. Παρακαλούμε δοκίμασε ξανά αργότερα." +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Επεξεργασία Ρυθμίσεων E-mail Διακομιστή" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1633 -#, python-format -msgid "There was an error sending the Test e-mail: %(res)s" -msgstr "Παρουσιάστηκε σφάλμα κατά την αποστολή του δοκιμαστικού e-mail:% (res)s" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." -msgstr "Παρακαλούμε ρύθμισε πρώτα τη διεύθυνση e-mail σου..." +#: 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:1637 -msgid "E-mail server settings updated" -msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Επεξεργασία χρήστη %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Κωδικός για επαναφορά %(user) χρήστη/ών" -#: cps/admin.py:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Προβολέας αρχείου φύλλου καταγραφής" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Αίτημα πακέτου ενημέρωσης" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Κατεβάζει πακέτο ενημέρωσης" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Ανοίγει πακέτο ενημέρωσης" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Αντικατάσταση αρχείων" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Οι συνδέσεις βάσης δεδομένων είναι κλειστές" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Σταματάει το διακομιστή" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Η ενημέρωση τελειώσε, παρακαλούμε πιέστε το εντάξει και φορτώστε ξανά τη σελίδα" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP Σφάλμα" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Σφάλμα σύνδεσης" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Τελείωσε ο χρόνος κατά την προσπάθεια δημιουργίας σύνδεσης" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Γενικό σφάλμα" -#: cps/admin.py:1773 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Το Αρχείο Ενημέρωσης Δεν Μπόρεσε Να Αποθηκευτεί σε" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Αποτυχία Δημιουργίας Τουλάχιστον Ενός Χρήστη LDAP" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Αποτυχία Δημιουργίας Τουλάχιστον Ενός Χρήστη LDAP" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Σφάλμα: %(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Σφάλμα: Δεν επιστράφηκε χρήστης σε απάντηση του διακομιστή LDAP" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Τουλάχιστον Ένας Χρήστης LDAP Δεν Βρέθηκε Στη Βάση Δεδομένων" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 -msgid "not installed" -msgstr "δεν εγκαταστάθηκε" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "Η Τοποθεσία DB δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "Λείπουν άδειες εκτέλεσης" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Η DB δεν μπορεί να Γραφτεί" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Η ειδικά προσαρμοσμένη στήλη No.%(column)d δεν υπάρχει στο επίπεδο βάσης δεδομένων" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Το Αρχειο Κλειδί Τοποθεσίας δεν είναι Έγκυρο, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Κανένα" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Η Τοποθεσία Certfile δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Η μορφή βιβλίου Διαγράφηκε Επιτυχώς" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Διαμόρφωση Λειτουργίας" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Oυπς! Ο επιλεγμένος τίτλος βιβλίου δεν είναι διαθέσιμος. Το αρχείο δεν υπάρχει ή δεν είναι προσβάσιμο" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Παρακαλούμε συμπλήρωσε όλα τα πεδία!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "επεξεργασία μεταδεδομένων" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "Το E-mail δεν είναι από έγκυρο domain" -#: cps/editbooks.py:457 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Προσθήκη νέου χρήστη" + +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +msgid "User '%(user)s' created" +msgstr "Χρήστης/ες '%(user)s' δημιουργήθηκαν" + +#: cps/admin.py:1926 +#, fuzzy +msgid "Oops! An account already exists for this Email. or name." +msgstr "Βρέθηκε ένας ήδη υπάρχον λογαριασμός για αυτή τη διεύθυνση e-mail ή όνομα χρήστη." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Χρήστης/ες '%(nick)s' διαγράφηκαν" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s δεν είναι μια έγκυρη γλώσσα" +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Δεν έχει απομείνει χρήστης διαχειριστής, δεν μπορεί να διαγραφεί ο χρήστης" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "Η επέκταση αρχείου '%(ext)s' δεν επιτρέπεται να ανέβει σε αυτό το διακομιστή" +msgid "User '%(nick)s' updated" +msgstr "Χρήστης/ες '%(nick)s' ενημερώθηκαν" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Το αρχείο προς ανέβασμα πρέπει να έχει μια επέκταση" +#: cps/converter.py:31 +msgid "not installed" +msgstr "δεν εγκαταστάθηκε" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Αποτυχεία δημιουργίας πορείας %(path)s (Η άδεια απορρήφθηκε)." +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Λείπουν άδειες εκτέλεσης" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Αποτυχία αποθήκευσης αρχείου %(file)s." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Μορφή αρχείου %(ext)s προστέθηκε σε %(book)s" +#: 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 "Κανένα" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Τα αναγνωριστικά δεν έχουν Διάκριση Πεζών-Κεφαλαίων Γραμμάτων, Αντικατάσταση Παλιού Αναγνωριστικού" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Τα μεταδεδομένα ενημερώθηκαν επιτυχώς" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Το αρχείο %(file)s ανέβηκε" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Η δομή πηγής ή προορισμού για μετατροπή λείπει" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Το βιβλίο είναι σε σειρά επιτυχώς για μετατροπή σε %(book_format)s" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Υπήρξε ένα σφάλμα στη μετατροπή αυτού του βιβλίου: %(res)s" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Το βιβλίο που ανέβηκε πιθανόν να υπάρχει στη βιβλιοθήκη, σκέψου να το αλλάξεις πριν ανεβάσεις νέο: " -#: cps/editbooks.py:1041 +#: 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: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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "Το αρχείο προς ανέβασμα πρέπει να έχει μια επέκταση" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Το αρχείο %(filename)s δεν μπόρεσε να αποθηκευτεί σε temp dir" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Αποτυχία Μετακίνησης Αρχείου Φόντου %(file)s: %(error)s" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Η μορφή βιβλίου Διαγράφηκε Επιτυχώς" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "επεξεργασία μεταδεδομένων" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Το αρχείο %(file)s ανέβηκε" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Η δομή πηγής ή προορισμού για μετατροπή λείπει" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Το βιβλίο είναι σε σειρά επιτυχώς για μετατροπή σε %(book_format)s" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Αποτυχεία δημιουργίας πορείας %(path)s (Η άδεια απορρήφθηκε)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Υπήρξε ένα σφάλμα στη μετατροπή αυτού του βιβλίου: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Αποτυχία αποθήκευσης αρχείου %(file)s." + +#: 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" @@ -618,187 +662,183 @@ msgstr "Η ανάκληση ονόματος δεν έχει επαληθευτ 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Αποστολή στο Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web δοκιμαστικό e-mail" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Δοκιμαστικό e-mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Ξεκινήστε με το Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 και αποστολή στο Kindle" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Αποστολή %(format)s στο Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Αποστολή στο Kindle" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Το αρχείου που χητήθηκε δεν μπορεί να διαβαστεί. Μπορεί να υπάρχουν λαθασμένες άδειες;" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Η διαγραφή βιβλίου %(id)s απέτυχε: %(message)s" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Η πορεία βιβλίου %(path)s δεν βρέθηκε στο Google Drive" -#: cps/helper.py:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Αυτό το όνομα χρήστη έχει ήδη παρθεί" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Σφάλμα Κατεβάσματος Φόντου" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Σφάλμα Μορφής Φόντου" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Αποτυχία δημιουργίας πορείας για φόντο" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Το αρχείο φόντου δεν είναι ένα έγκυρο αρχείο εικόνας, ή δεν μπόρεσε να αποθηκευτεί" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Μόνο jpg/jpeg αρχεία υποστηρίζονται ως αρχεία φόντου" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Δεν βρέθηκε δυαδικό αρχείο Unrar" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Σφάλμα εκτέλεσης UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Αναμονή" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Απέτυχε" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Ξεκίνησε" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Τελείωσε" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Ανακάλυψε" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "ʼΑγνωστη κατάσταση" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Καθορισμός Kobo" @@ -807,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:1613 +#: 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 @@ -868,12 +908,13 @@ msgstr "Google Oauth σφάλμα, παρακαλούμε δοκίμασε ξα msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "Σύνδεση" @@ -889,497 +930,619 @@ msgstr "Η μάρκα έχει λήξει" msgid "Success! Please return to your device" msgstr "Επιτυχία! Παρακαλούμε επέστρεψε στη συσκευή σου" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Βιβλία" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Προβολή πρόσφατων βιβλίων" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Βιβλία στη Μόδα" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Προβολή Βιβλίων στη Μόδα" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Κατεβασμένα Βιβλία" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Βιβλία με Κορυφαία Αξιολόγηση" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Προβολή διαβασμένων και αδιάβαστων" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Προβολή αδιάβαστων" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Ανακάλυψε" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Αξιολογήσεις" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Μορφές αρχείου" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Αρχειοθετημένα Βιβλία" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Λίστα Βιβλίων" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Προβολή Λίστας Βιβλίων" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Αναζήτηση" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Εκδόθηκε μετά" + +#: cps/search.py:195 +msgid "Published before " +msgstr "Εκδόθηκε πριν" + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Αξιολόγηση <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Αξιολόγηση >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Προχωρημένη Αναζήτηση" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Διευκρινίστηκε μη έγκυρο ράφι" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Συγγνώμη δεν σου επιτρέπεται να προσθέσεις ένα βιβλίο στο ράφι: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Το βιβλίο είναι ήδη μέρος αυτού του ραφιού: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Το βιβλίο έχει προστεθεί στο ράφι: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Τα βιβλία είναι ήδη μέρος του ραφιού: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Βιβλία είχαν προστεθεί στο ραφι: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Δεν μπόρεσε να γίνει η προσθήκη βιβλίων στο ράφι: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Το βιβλίο έχει αφαιρεθεί από το ράφι: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Δημιούργησε ένα Ράφι" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Συγγνώμη αλλά δεν σου επιτρέπεται η αφαίρεση ενός βιβλίου από αυτό το ράφι: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Επεξεργασία ενός ραφιού" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Αλλαγή σειράς του Ραφιού: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Το ράφι %(title)s δημιουργήθηκε" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Το ράφι %(title)s άλλαξε" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Υπήρξε ένα σφάλμα" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Ένα δημόσιο ράφι με το όνομα '%(title)s' υπάρχει ήδη." -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Ένα ιδιωτικό ράφι με το όνομα '%(title)s' υπάρχει ήδη." -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Αλλαγή σειράς του Ραφιού: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Ράφι: '%(name)s" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Σφάλμα κατά το άνοιγμα του ραφιού. Το ράφι δεν υπάρχει ή δεν είναι προσβάσιμο" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Εργασίες" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Αναμονή" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Απέτυχε" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Ξεκίνησε" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Τελείωσε" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: 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 "Απρόβλεπτα δεδομένα κατά την ανάγνωση των πληροφοριών ενημέρωσης" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Δεν υπάρχει διαθέσιμη ενημέρωση. Έχεις ήδη την τελευταία έκδοση εγκατεστημένη" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Μια νέα ενημέρωση είναι διαθέσιμη. Κάνε κλικ στο κουμπί πιο κάτω για να ενημερώσεις με την τελευταία έκδοση." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Δεν μπόρεσε να συγκεντρώσει τις πληροφορίες ενημέρωσης" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Κάνε κλικ στο κουμπί πιο κάτω για να ενημερώσεις με την τελευταία σταθερή έκδοση." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Μια νέα ενημέρωση είναι διαθέσιμη. Κάνε κλικ στο κουμπί πιο κάτω για ενημέρωση με την έκδοση: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Δεν υπάρχουν διαθέσιμες πληροφορίες αποδέσμευσης" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Ανακάλυψε (Τυχαία Βιβλία)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Βιβλία στη Μόδα (Με τα περισσότερα κατεβάσματα)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Κατεβασμένα βιβλία από %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Συγγραφέας: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Εκδότης: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Σειρές: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Αξιολόγηση: %(rating)s stars" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Μορφή αρχείου: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Κατηγορία: %(name)s" -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "Γλώσσα: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Προχωρημένη Αναζήτηση" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Αναζήτηση" +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Γλώσσα: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Κατεβασμένα" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Λίστα αξιολογήσεων" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Λίστα μορφών αρχείου" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Εργασίες" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Εκδόθηκε μετά" - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Εκδόθηκε πριν" - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Αξιολόγηση <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Αξιολόγηση >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Παρακαλούμε διαμόρφωσε πρώτα τις ρυθμίσεις ταχυδρομείου SMTP..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(eReadermail)s" -#: cps/web.py:1531 +#: 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 "Oυπς! Υπήρξε ένα σφάλμα κατά την αποστολή αυτού του βιβλίου: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Δεν μπόρεσε να ενεργοποιηθεί η επαλήθευση LDAP" -#: cps/web.py:1621 -#, 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:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Δεν μπόρεσε να συνδεθεί: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Λανθασμένο Όνομα Χρήστη ή Κωδικός" -#: cps/web.py:1638 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Ο Νέος Κωδικός έχει σταλεί στη διεύθυνση email σου" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Το εργαλείο μετατροπής Calibre ebook %(tool)s δεν βρέθηκε" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s μορφή δεν βρέθηκε σε δίσκο" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "Ο μετατροπέας Ebook απέτυχε με άγνωστο σφάλμα" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Ο μετατροπέας Kepubify απέτυχε: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Το τροποποιημένο αρχείο δεν βρέθηκε ή υπάρχουν περισσότερα από ένα αρχεία στο φάκελο %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Ο μετατροπέας Ebook απέτυχε: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Το Calibre απέτυχε με σφάλμα: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "επεξεργασία μεταδεδομένων" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Ανέβασμα" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Χρήστες" @@ -1392,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Διεύθυνση E-mail Αποστολής στο Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Διαχειριστής" @@ -1409,13 +1573,8 @@ msgstr "Διαχειριστής" msgid "Password" msgstr "Κωδικός" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Ανέβασμα" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "Κατέβασμα" @@ -1429,7 +1588,7 @@ msgstr "Προβολή Βιβλίων" msgid "Edit" msgstr "Επεξεργασία" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1440,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 @@ -1470,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 @@ -1542,78 +1697,109 @@ msgstr "Επεξεργασία Βασικής Διαμόρφωσης" msgid "Edit UI Configuration" msgstr "Επεξεργασία Διαμόρφωσης UI" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Προβολή Φύλλων Καταγραφής" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Επανασύνδεση Βάσης Δεδομένων Calibre" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Επανεκκίνηση" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Κλείσιμο" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Ενημέρωση" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Έκδοση" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Λεπτομέρειες" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Τρέχουσα έκδοση" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Έλεγχος για Ενημέρωση" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Πραγματοποίηση Ενημέρωσης" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις επανεκκίνηση" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις κλείσιμο;" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Γίνεται ενημέρωση, παρακαλούμε μη φορτώσεις ξανά αυτή τη σελίδα" @@ -1625,39 +1811,39 @@ msgstr "μέσω" msgid "In Library" msgstr "Στη Βιβλιοθήκη" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "μείωση" @@ -1665,165 +1851,166 @@ msgstr "μείωση" msgid "More by" msgstr "Περισσότερα από" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Διαγραφή Βιβλίου" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Διαγραφή μορφών:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Μετατροπή μορφής βιβλίου:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Μετατροπή από:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "διάλεξε μια επιλογή" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Μετατροπή σε:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Μετατροπή βιβλίου" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Τίτλος Βιβλίου" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Συγγραφέας" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Περιγραφή" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Αναγνωριστικά" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Είδος Αναγνωριστικού" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Τιμή Αναγνωριστικού" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Αφαίρεση" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Προσθήκη Αναγνωριστικού" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Ετικέτες" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "Ταυτότητα Σειράς" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Αξιολόγηση" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Συγκέντρωση Εξώφυλλου από URL (JPEG - Η εικόνα θα κατέβει και θα αποθηκευτεί σε βάση δεδομένων)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Ανέβασμα Εξώφυλλου από Τοπικό Δίσκο" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Ημερομηνία Έκδοσης" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Εκδότης" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "Όχι" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Μορφή Ανεβάσματος" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Προβολή Βιβλίου σε Αποθήκευση" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Συγκέντρωση Μεταδεδομένων" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Αποθήκευση" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Λέξη κλειδί" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr "Αναζήτηση λέξης κλειδιού" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Κάνε κλικ στο εξώφυλλο για φόρτωση μεταδεδομένων στη φόρμα" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Φόρτωση..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "Κλείσιμο" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Πηγή" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Σφάλμα αναζήτησης!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Δεν βρέθηκε(αν) αποτέλεσμα(τα)! Παρακαλούμε δοκίμασε μια άλλη λέξη κλειδί." @@ -1916,7 +2103,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1932,6 +2119,7 @@ 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 "Είσαι πραγματικά σίγουρος/η;" @@ -2037,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 @@ -2053,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 @@ -2243,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 "Προβολή Διαμόρφωσης" @@ -2255,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 "Θέμα" @@ -2346,79 +2580,82 @@ msgstr "Προσθήκη ετικετών Επιτρέπεται/Απορρίπ msgid "Add Allowed/Denied custom column values" msgstr "Προσθήκη τιμών ειδικά κατασκευασμένων στηλών Επιτρέπεται/Απορρίπτεται" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Διάβασε στο Πρόγραμμα Περιήγησης" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "ʼΑκουσε στο Πρόγραμμα Περιήγησης" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Εκδόθηκε" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Σήμανση ως Αδιάβαστο" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Σήμανση ως Διαβασμένο" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Διαβάστηκε" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Επαναφορά από το αρχείο" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Προσθήκη στο αρχείο" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Αρχειοθετήθηκε" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Περιγραφή" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Προσθήκη στο ράφι" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2442,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:29 +#: 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 "Πίσω" @@ -2471,188 +2709,196 @@ msgstr "Όνομα domain" msgid "Denied Domains (Blacklist)" msgstr "Domains που Απορρίφθηκαν (Μαύρη λίστα)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Kobo Μονάδα Συγχρονισμού" -#: cps/templates/http_error.html:31 +#: 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-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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Κεντρική" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Αλλαγή Θέσης Περιήγησης" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Αναζήτηση Βιβλιοθήκης" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "Φόρτωση..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Σφάλμα" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Το ανέβασμα έγινε, γίνεται επεξεργασία, παρακαλούμε περίμενε..." -#: cps/templates/layout.html:76 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 "Ρυθμίσεις" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Λογαριασμός" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Αποσύνδεση" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Παρακαλούμε μην ανανεώσεις τη σελίδα" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Περιήγηση" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Σχετικά" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Προηγούμενο" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Λεπτομέρειες Βιβλίου" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Να με Θυμάσαι" @@ -2661,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 "Σύνδεση με το Μαγικό Σύνδεσμο" @@ -2757,7 +3003,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Βιβλίο" @@ -2771,128 +3017,162 @@ msgstr "Calibre-Web Κατάλογος eBook" msgid "epub Reader" msgstr "PDF πρόγραμμα ανάγνωσης" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Φωτεινό" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "Πίσω" + +#: 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:116 -msgid "Light" -msgstr "Φωτεινό" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Σκοτεινό" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Σελίδα διαχειριστή" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2901,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 πρόγραμμα ανάγνωσης" @@ -2920,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 @@ -2939,15 +3219,19 @@ msgstr "Με την επαλήθευση, θα συνδεθείτε αυτόμα msgid "This verification link will expire in 10 minutes." msgstr "Αυτός ο σύνδεσμος επαλήθευσης θα λήξει σε 10 λεπτά." -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Δεν Βρέθηκαν Αποτελέσματα" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Όρος Αναζήτησης:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Αποτελέσματα για:" @@ -2959,64 +3243,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Διαγραφή αυτού του Ραφιού" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3061,8 +3353,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Πρόγραμμα Βιβλιοθήκης" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3088,9 +3380,17 @@ 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 "" + +#: 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" @@ -3156,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Διεύθυνση E-mail Αποστολής στο Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Δοκιμαστικό e-mail" #: cps/templates/user_table.html:137 @@ -3236,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 c8c6ae9e..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 63bc1161..f1015f3f 100644 --- a/cps/translations/es/LC_MESSAGES/messages.po +++ b/cps/translations/es/LC_MESSAGES/messages.po @@ -9,605 +9,649 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: es \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" # "Last-Translator: victorhck \n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Estadísticas" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Reconexión correcta" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando desconocido" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Página de administración" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuración básica" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuración de la interfaz de usuario" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Editar usuarios" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Usuario no encontrado" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} usuarios eliminados con éxito" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Petición mal formulada" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "El invitado no puede tener ese rol" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Rol inválido" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "El invitado no puede tener esta vista" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Vista no válida" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "No hay un sitio válido" -#: cps/admin.py:498 +#: 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:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parámetro no encontrado" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Columna de lectura no válida" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Columna restringida no válida" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuración de Calibre-Web actualizada" -#: cps/admin.py:591 +#: 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:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "¿Realmente deseas borrar este dominio?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "¿Realmente quieres borrar este usuario?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "¿Realmente quieres eliminar este estante?" -#: cps/admin.py:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "Etiqueta no encontrada" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Acción no válida" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Etiqueta no encontrada" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Acción no válida" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Por favor, introduce una cuenta de servicio LDAP" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Error en la base de datos: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "La base de datos no es modificable" - -#: cps/admin.py:1266 -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:1270 -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:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Actualizados los ajustes del servidor de correo electrónico" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Configuración de la base de datos" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "¡Por favor, rellena todos los campos!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "El correo electrónico no tiene un dominio válido" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Añadir un nuevo usuario" - -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Usuario '%(user)s' creado" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Encontrada una cuenta existente para este correo electrónico o nombre de usuario." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Usuario '%(nick)s' eliminado" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "No puedes borrar al Usuario Invitado" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Añadir nuevo usuario" -#: cps/admin.py:1469 -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:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Cambiar parámetros de correo" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Editar Usuario %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Usuario '%(nick)s' actualizado" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "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:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Cambiar parámetros de correo" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "Verificación de cuenta de Gmail exitosa" +msgid "Oops! Database Error: %(error)s." +msgstr "Error en la base de datos: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Por favor, configure su correo electrónico primero..." -#: cps/admin.py:1637 -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:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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 "Ha ocurrido un error desconocido. Por favor vuelva a intentarlo más tarde." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Editar Usuario %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visor del fichero de log" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Solicitando paquete de actualización" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Descargando paquete de actualización" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Descomprimiendo paquete de actualización" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Remplazando archivos" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Los conexiones con la base datos están cerradas" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Parando el servidor" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Error de conexión" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Error general" -#: cps/admin.py:1773 +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Error: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Usuario importado con éxito" -#: cps/converter.py:30 -msgid "not installed" -msgstr "no instalado" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Faltan permisos de ejecución" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "La base de datos no es modificable" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Columna personalizada No.%(column)d no existe en la base de datos calibre" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Ninguno" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Formato de libro eliminado con éxito" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Libro eliminado con éxito" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "Actualizados los ajustes del servidor de correo electrónico" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Configuración de la base de datos" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "¡Por favor, rellena todos los campos!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "editar metadatos" +#: 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:1909 +msgid "Add new user" +msgstr "Añadir un nuevo usuario" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex) no es un número válido, saltando" +msgid "User '%(user)s' created" +msgstr "Usuario '%(user)s' creado" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s no es un idioma válido" +#: cps/admin.py:1926 +#, fuzzy +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/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Usuario '%(nick)s' eliminado" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "No puedes borrar al Usuario Invitado" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Usuario '%(nick)s' actualizado" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "El archivo a subir debe tener una extensión" +#: cps/converter.py:31 +msgid "not installed" +msgstr "no instalado" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Fallo al crear la ruta %(path)s (permiso denegado)" +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Faltan permisos de ejecución" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Fallo al guardar el archivo %(file)s." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Archivo con formato %(ext)s añadido a %(book)s" +#: 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 "Ninguno" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadatos actualizados con éxito" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "El fichero %(file)s ha sido subido" + +#: 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: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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Formato de libro eliminado con éxito" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Libro eliminado con éxito" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "editar metadatos" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "El fichero %(file)s ha sido subido" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex) no es un número válido, saltando" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Falta la fuente o el formato de destino para la conversión" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, 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" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Fallo al crear la ruta %(path)s (permiso denegado)" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Ocurrió un error al convertir este libro: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Fallo al guardar el archivo %(file)s." + +#: 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" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -622,187 +666,184 @@ msgstr "El dominio Callback no se ha verificado, siga los pasos para verificarlo 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Enviar al Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Comprobar correo electrónico" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Primeros pasos con Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 y enviar al Kindle" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: 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 al Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Enviar al Kindle" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Este nombre de usuario ya está en uso" -#: cps/helper.py:669 -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:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Error al descargar la cubierta" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Error en el formato de la cubierta" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Error al crear una ruta para la cubierta" -#: cps/helper.py:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "No se encuentra el archivo binario UnRar" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Error ejecutando UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Esperando" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Fallido" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Comenzado" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Finalizado" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Descubrir" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Estado desconocido" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuración de Kobo" @@ -811,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:1613 +#: 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 @@ -872,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:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Estrellas" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -893,497 +935,619 @@ msgstr "El token ha expirado" msgid "Success! Please return to your device" msgstr "¡Correcto! Por favor regrese a su dispositivo" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Libros" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Mostrar libros recientes" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Mostrar libros populares" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Libros Descargados" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Mostrar no leído" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Descubrir" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Calificaciones" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Libros archivados" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista de Libros" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Buscar" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Publicado después de " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publicado antes de " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Calificación <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Calificación >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Estado de lectura = $(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Búsqueda avanzada" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Estantería especificada no válida" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Lo sentimos, no tiene permisos para agregar un libro al estante: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "El libro ya forma parte del estante: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "El libro fue agregado a el estante: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Los libros ya forman parte del estante: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Los libros han sido añadidos al estante: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "No se pudieron agregar libros al estante: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "El libro fue eliminado del estante: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crear un estante" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Lo siento, no tiene permiso para eliminar un libro del estante: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Editar un estante" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Libro eliminado con éxito" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Cambiar orden del estante: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Estante %(title)s creado" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Estante %(title)s cambiado" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Ha sucedido un error" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Libro eliminado con éxito" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Cambiar orden del estante: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Estante: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Tareas" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Esperando" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Fallido" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Comenzado" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Finalizado" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Estado desconocido" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Dato inesperado mientras se leía la información de actualización" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Actualización no disponible. Ya tienes instalada la versión más reciente" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Una nueva actualización está disponible. Haz clic en el botón inferior para actualizar a la versión más reciente." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "No se puede conseguir información sobre la actualización" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Haz clic en el botón de abajo para actualizar a la última versión estable." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Hay una nueva actualización disponible. Haz clic en el botón de abajo para actualizar a la versión: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "No hay información del lanzamiento disponible" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Descubrir (Libros al azar)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Libros populares (los más descargados)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Libros descargados por %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor/es: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editor/es: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Series: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Calificación: %(rating)s estrellas" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" -msgstr "Formato del archivo: %(format)s" - -#: cps/web.py:663 -#, python-format -msgid "Category: %(name)s" -msgstr "Categoría : %(name)s" - -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "Idioma: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Búsqueda avanzada" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Buscar" - -#: cps/templates/admin.html:16 cps/web.py:979 -msgid "Downloads" -msgstr "Descargas" - -#: cps/web.py:1068 -msgid "Ratings list" -msgstr "Lista de calificaciones" - -#: cps/web.py:1095 -msgid "File formats list" -msgstr "Lista de formatos" - -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Tareas" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Publicado después de " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Publicado antes de " +msgstr "Formato del archivo: %(format)s" -#: cps/web.py:1315 +#: cps/web.py:682 #, python-format -msgid "Rating <= %(rating)s" -msgstr "Calificación <= %(rating)s" +msgid "Category: %(name)s" +msgstr "Categoría : %(name)s" -#: cps/web.py:1317 +#: cps/web.py:711 #, python-format -msgid "Rating >= %(rating)s" -msgstr "Calificación >= %(rating)s" +msgid "Language: %(name)s" +msgstr "Idioma: %(name)s" -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Estado de lectura = $(status)s" +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Descargas" -#: cps/web.py:1425 -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/web.py:1051 +msgid "Ratings list" +msgstr "Lista de calificaciones" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Lista de formatos" + +#: 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:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Libro puesto en la cola de envío a %(kindlemail)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:1531 +#: 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 "Ha sucedido un error en el envío del libro: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: 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:1621 -#, 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:1627 -#, 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:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Usuario o contraseña inválido" -#: cps/web.py:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Calibre ebook-convert %(tool)s no encontrado" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s format no encontrado en disco" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "El conversor de Ebook falló con un error desconocido" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify-converter falló: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Archivo convertido no encontrado, o más de un archivo en el directorio %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Falló Ebook-converter: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre falló con el error: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "editar metadatos" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Subir archivo" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Usuarios" @@ -1396,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Enviar al correo de Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1413,13 +1578,8 @@ msgstr "Admin" msgid "Password" msgstr "Contraseña" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Subir archivo" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1433,7 +1593,7 @@ msgstr "Ver libros" msgid "Edit" msgstr "Editar" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1444,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 @@ -1474,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 @@ -1546,78 +1703,109 @@ msgstr "Editar la configuración básica" msgid "Edit UI Configuration" msgstr "Editar la configuración de la interfaz de usuario" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Administración" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Descargar paquete de debug" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Ver archivos de registro" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Reconectar a la BD Calibre" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Reiniciar" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Apagar" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Actualizar" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versión" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detalles" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versión actual" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Comprobar actualizaciones" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Realizar actualización" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "¿Realmente quieres reiniciar?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "¿Realmente quiere detener?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Actualizando. Por favor, no recargue la página" @@ -1629,39 +1817,39 @@ msgstr "via" msgid "In Library" msgstr "En la Librería" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 en base a fecha del libro, más reciente primero" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 en base a fecha del libro, menos reciente primero" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 en base al título en orden alfabético" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 en base al título en orden alfabético invertido" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 en base a fecha de publicación, más reciente primero" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 en base a fecha de publicación, menos reciente primero" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "reducir" @@ -1669,165 +1857,166 @@ msgstr "reducir" msgid "More by" msgstr "Más de" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Borrar libro" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Borrar formatos:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Convertir formato de libro:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Convertir desde:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "seleccionar una opción" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Convertir a:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Convertir libro" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Título del libro" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Descripción" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identificadores" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Tipo de identificador" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Valor de identificador" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Borrar" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Añadir identificador" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etiquetas" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID de serie" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Clasificación" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Obtener portada de URL (JPEG, la portada ser'a descargada y almacenada en la base de datos)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Subir portada desde un disco local" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Fecha de publicación" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Editor" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Subir formato" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Ver libro tras la edición" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Obtener metadatos" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Palabra clave" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Buscar por palabras clave " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Haz clic en la portada para cargar los metadatos en el formulario" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Cargando..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Origen" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "¡Error en la búsqueda!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "¡No se encontraron resultados! Por favor intenta con otra palabra clave." @@ -1920,7 +2109,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1936,6 +2125,7 @@ msgid "Enter " msgstr "Identificadores" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "¿Estás realmente seguro?" @@ -2041,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 @@ -2057,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 @@ -2247,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" @@ -2259,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" @@ -2350,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Leer en el navegador" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Escuchar en el navegador" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicado" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marcar como no leido" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marcar como leido" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Leído" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restarurar desde el archivo" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Añadir a archivación" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivado" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descripción:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2446,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:29 +#: 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" @@ -2475,188 +2716,196 @@ msgstr "Introducir nombre de dominio" msgid "Denied Domains (Blacklist)" msgstr "Dominios prohibidos (Blaclist)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Token de sincronización de Kobo" -#: cps/templates/http_error.html:31 +#: 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 "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" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Ordenar autores en orden alfabético" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: 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 en orden alfabético inverso" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Ordenar ascendientemente en base al índice de serie" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Inicio" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Alternar navegación" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Buscar en la librería" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Cuenta" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Cerrar sesión" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Cargando..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Error" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Carga hecha, procesando, por favor espere ..." -#: cps/templates/layout.html:76 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 "Ajustes" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Cuenta" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Cerrar sesión" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Por favor, no actualice la página" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Navegar" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Acerca de" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Previo" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Detalles del libro" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Recordarme" @@ -2665,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" @@ -2761,7 +3010,7 @@ msgstr "Directorio padre" msgid "Select" msgstr "Seleccionar" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Ok" @@ -2775,128 +3024,162 @@ msgstr "Catálogo de ebooks de Calibre-Web" msgid "epub Reader" msgstr "Lector PDF" -#: cps/templates/read.html:75 +#: 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 "Oscuro" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Regresar" + +#: 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:116 -msgid "Light" -msgstr "Claro" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Oscuro" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Página de administración" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2905,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" @@ -2924,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 @@ -2943,15 +3226,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "No se han encontrado resultados" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Término de búsqueda:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Resultados para:" @@ -2963,64 +3250,72 @@ 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:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Borrar este estante" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Editar propiedades del estante" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Ordenar libros manualmente" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Deshabilitar cambio de orden" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Habilitar cambio de orden" @@ -3065,8 +3360,8 @@ msgid "System Statistics" msgstr "Estadísticas del sistema" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Biblioteca del programa" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3092,9 +3387,17 @@ 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 "" + +#: 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" @@ -3160,18 +3463,18 @@ 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 Kindle 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 "Kindle E-mail" -msgstr "Correo electrónico Kindle" +msgid "eReader Email" +msgstr "Comprobar correo electrónico" #: cps/templates/user_table.html:137 #, fuzzy @@ -3241,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 ecb99d14..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 09dee98c..af37874f 100644 --- a/cps/translations/fi/LC_MESSAGES/messages.po +++ b/cps/translations/fi/LC_MESSAGES/messages.po @@ -7,601 +7,645 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Tilastot" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Ylläpitosivu" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Perusasetukset" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Käyttöliittymän asetukset" -#: cps/admin.py:289 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:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web asetukset päivitetty" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Oletko varma, että haluat poistaa hyllyn?" -#: cps/admin.py:599 +#: 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:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "" - -#: cps/admin.py:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Muuta SMTP asetuksia" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: 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 "" -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Sähköpostipalvelimen tiedot päivitetty" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Ominaisuuksien asetukset" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Ole hyvä ja täytä kaikki kentät!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "Sähköpostiosoite ei ole toimivasta domainista" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Lisää uusi käyttäjä" - -#: cps/admin.py:1427 +#: cps/admin.py:1323 #, python-format -msgid "User '%(user)s' created" -msgstr "Käyttäjä '%(user)s' lisätty" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Tälle sähköpostiosoitteelle tai tunnukselle löytyi jo tili." +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "" -#: cps/admin.py:1463 +#: cps/admin.py:1326 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "Käyttäjä '%(nick)s' poistettu" +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:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1469 -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:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Muokkaa käyttäjää %(nick)s" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Käyttäjä '%(nick)s' päivitetty" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Sähköpostipalvelimen tiedot päivitetty" -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Tapahtui tuntematon virhe. Yritä myöhemmin uudelleen." +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Muuta SMTP asetuksia" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1633 -#, 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: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:1635 -msgid "Please configure your e-mail address first..." +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1637 -msgid "E-mail server settings updated" -msgstr "Sähköpostipalvelimen tiedot päivitetty" - -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Muokkaa käyttäjää %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Lokitiedoston katselin" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Haetaan päivitystiedostoa" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Ladataan päivitystiedostoa" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Puretaan päivitystiedostoa" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Korvataan tiedostoja" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Tietokantayhteydet on katkaistu" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Sammutetaan palvelin" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Yhteysvirhe" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Aikakatkaisu yhteyttä luotaessa" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Yleinen virhe" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: 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:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Ominaisuuksien asetukset" + +#: 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:1903 +msgid "E-mail is not from valid domain" +msgstr "Sähköpostiosoite ei ole toimivasta domainista" + +#: 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:1926 +#, fuzzy +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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Käyttäjä '%(nick)s' poistettu" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Käyttäjä '%(nick)s' päivitetty" + +#: cps/converter.py:31 msgid "not installed" msgstr "ei asennettu" -#: cps/converter.py:31 +#: cps/converter.py:32 msgid "Execution permissions missing" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:917 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:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 +#: 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:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: 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:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadata päivitetty onnistuneesti" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Tiedosto %(file)s tallennettu" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "muokkaa metadataa" +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Lähteen tai kohteen tiedostomuoto puuttuu" -#: cps/editbooks.py:457 +#: cps/editbooks.py:337 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Kirja lisätty muutosjonoon muotoon %(book_format)s" + +#: 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:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: 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:634 -msgid "User has no rights to upload additional file formats" -msgstr "" - -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: 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:643 cps/editbooks.py:1033 +#: 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:655 +#: cps/editbooks.py:753 #, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Polun %(path)s luonti epäonnistui (Ei oikeutta)." - -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Tiedoston %(file)s tallennus epäonnistui." +msgid "File %(filename)s could not saved to temp dir" +msgstr "" -#: cps/editbooks.py:683 +#: cps/editbooks.py:773 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Tiedostoformaatti %(ext)s lisätty %(book)s" - -#: cps/editbooks.py:697 cps/editbooks.py:809 -msgid "User has no rights to upload cover" +msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:828 -msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:869 -msgid "Metadata successfully updated" -msgstr "Metadata päivitetty onnistuneesti" - -#: cps/editbooks.py:887 -msgid "Error editing book: {}" +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:951 -msgid "Uploaded book probably exists in the library, consider to change before upload new: " +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "muokkaa metadataa" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(filename)s could not saved to temp dir" +msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1061 -#, python-format -msgid "Failed to Move Cover File %(file)s: %(error)s" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:1195 #, python-format -msgid "File %(file)s uploaded" -msgstr "Tiedosto %(file)s tallennettu" - -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Lähteen tai kohteen tiedostomuoto puuttuu" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Polun %(path)s luonti epäonnistui (Ei oikeutta)." -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1200 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Kirja lisätty muutosjonoon muotoon %(book_format)s" +msgid "Failed to store file %(file)s." +msgstr "Tiedoston %(file)s tallennus epäonnistui." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1224 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Kirjan muunnoksessa tapahtui virhe: %(res)s" +msgid "File format %(ext)s added to %(book)s" +msgstr "Tiedostoformaatti %(ext)s lisätty %(book)s" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -616,186 +660,181 @@ msgstr "Paluuosoitteen domain ei ole varmistettu, seuraa ohjeita vamistaaksesi s 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Lähetä Kindleen" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Testi sähköposti" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Aloita Calibre-Web:in käyttö" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Lähetä %(format)s Kindleen" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Lähetä Kindleen" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Odottaa" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Epäonnistui" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Aloitettu" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Valmistui" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Löydä" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Tuntematon tila" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -804,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:1613 +#: 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 @@ -865,12 +904,13 @@ msgstr "Google Oauth virhe, yritä myöhemmin uudelleen." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -886,497 +926,618 @@ msgstr "Valtuutus vanhentunut" msgid "Success! Please return to your device" msgstr "Onnistui! Ole hyvä ja palaa laitteellesi" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Kirjat" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Näytä viimeisimmät kirjat" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Näytä kuumat kirjat" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Näyt lukemattomat" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Löydä" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Arvostelut" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Tiedotomuodot" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Hae" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Julkaistu alkaen " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Julkaisut ennen " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Arvostelu <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Arvostelu >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Edistynyt haku" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Virheellinen hylly valittu" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Valitettavasti sinulla ei ole oikeutta lisätä kirjaa hyllyyn: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Kirja on jo hyllyssä: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Kirja on lisätty hyllyyn: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Kirjat on jo osa hyllyssä: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Kirjat on lisätty hyllyyn: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Kirjojen lisäys hyllyyn: %(sname)s epäonnistui" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Kirja on poistettu hyllystä: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "luo hylly" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Valitettavsti sinulla ei ole oikeutta poistaa kirjaa hyllystä: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Muokkaa hyllyä" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Metadata päivitetty onnistuneesti" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Muuta hyllyn: '%(name)s' järjestystä" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Hylly %(title)s luotu" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Hylly %(title)s muutettu" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Tapahtui virhe" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Metadata päivitetty onnistuneesti" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Muuta hyllyn: '%(name)s' järjestystä" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Hylly: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: 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:62 +msgid "Waiting" +msgstr "Odottaa" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Epäonnistui" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Aloitettu" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Valmistui" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Tuntematon tila" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Odottamatonta tietoa luettaessa päivitystietoa" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Ei päivitystä saatavilla. Sinulla on jo uusin versio" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Uusi päivitys saatavilla. Paina alla olevaa nappia päivittääksesi uusimpaan versioon." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Päivitystiedon hakeminen epäonnistui" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Paina alla olevaa nappia päivittääksesi uusimpaan vakaaseen versioon." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Uusi päivitys saatavilla. Paina alla olevaa nappia päivittääksesi versioon: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Ei päivitystietoa saatavilla" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Löydä (satunnaiset kirjat)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Kuumat kirjat (ladatuimmat)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Kirjailija: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Julkaisija: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Sarja: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Arvostelu: %(rating)s tähteä" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Tiedostomuoto: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategoria: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Kieli: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Edistynyt haku" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Hae" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "DLS" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Arvostelulistaus" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Tiedostomuotolistaus" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Tehtävät" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Julkaistu alkaen " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Julkaisut ennen " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Arvostelu <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Arvostelu >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Ole hyvä ja aseta SMTP postiasetukset ensin..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Kirja lisätty onnistuneeksi lähetettäväksi osoitteeseen %(kindlemail)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:1531 +#: 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 "Kirjan: %(res)s lähettämisessa tapahtui virhe" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP autnetikoinnin aktivointi ei onnistu" -#: cps/web.py:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: 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:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "E-kirjan muunnos epäonnistui: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "muokkaa metadataa" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Lähetä" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Käyttäjälista" @@ -1389,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Ylläpito" @@ -1406,13 +1568,8 @@ msgstr "Ylläpito" msgid "Password" msgstr "Salasana" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Lähetä" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1426,7 +1583,7 @@ msgstr "Näytä ekirjat" msgid "Edit" msgstr "Muokkaa" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1437,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 @@ -1467,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 @@ -1539,78 +1692,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Ylläpito" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Katsele lokitiedostoja" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Uudelleenyhdistä Calibre DB" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Uudellenkäynnistä Calibre-Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Sammuta Calibre-Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Päivitä" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versio" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Yksityiskohdat" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Nykyinen versio" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Tarkista päivitykset" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Päivitä" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Haluatko varmasti uudelleenkäynnistää Calibre-Webin?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Haluatko varmasti pysäyttää Calibre-Webin?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Päivitetään, älä päivitä sivua" @@ -1622,39 +1806,39 @@ msgstr "" msgid "In Library" msgstr "Kirjastossa" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "vähennä" @@ -1662,165 +1846,166 @@ msgstr "vähennä" msgid "More by" msgstr "Enemmän" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Poista kirja" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Poista tiedostomuodot:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Muunna kirjan tiedostomuoto:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Muunna muodosta:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "valitse vaihtoehto" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Muunna muotoon:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Muunna kirja" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Kirjan otsikko" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Kirjailija" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Kuvaus" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tunnisteet" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Arvostelu" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Kannen osoite (jpg, kuva ladataan ja tallennetaan tietokantaan, kenttä jää uudelleen tyhjäksi)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Lataa kuva paikalliselta levyltä" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Julkaisupäivä" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Julkaisija" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Lataa tiedostomuoto" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "katso kirjaa muokkauksen jälkeen" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Hae metadata" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Avainsana" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Hae avainsanaa " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Klikkaa kantta ladataksesi metadata lomakkeelle" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Ladataan..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Lähde" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Hakuvirhe!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Ei osumia! Kokeile jotain tosita hakusanaa." @@ -1913,7 +2098,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1929,6 +2114,7 @@ msgid "Enter " msgstr "Rekisteröi" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Oletko aivan varma?" @@ -2033,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 @@ -2049,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 @@ -2239,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" @@ -2251,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" @@ -2342,79 +2574,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lue selaimessa" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Kuuntele selaimessa" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Merkitse lukemattomaksi" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Merkitse luetuksi" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Luettu" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Kuvaus:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2438,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:29 +#: 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" @@ -2467,186 +2703,194 @@ msgstr "Syötä domainnimi" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Koti" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Vaihda navigointi" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Tili" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Kirjaudu ulos" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Ladataan..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Virhe" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Lataus tehty, prosessoidaan, ole hyvä ja odota..." -#: cps/templates/layout.html:76 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 "Asetukset" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Tili" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Kirjaudu ulos" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Selaa" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Tietoja" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Edellinen" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Kirjan tiedot" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Muista minut" @@ -2655,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" @@ -2751,7 +2995,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Kirja" @@ -2765,128 +3009,162 @@ msgstr "Calibre-Web e-kirjaluettelo" msgid "epub Reader" msgstr "PDF lukija" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Vaalea" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Tumma" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Palaa" + +#: 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:116 -msgid "Light" -msgstr "Vaalea" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Tumma" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Ylläpitosivu" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2895,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" @@ -2914,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 @@ -2933,15 +3211,19 @@ 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/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Tulosket haulle:" @@ -2953,64 +3235,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Poista tämä hylly" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3055,8 +3345,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Ohjelmiston luokka" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3082,9 +3372,17 @@ 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 "" + +#: 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" @@ -3150,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Testi sähköposti" #: cps/templates/user_table.html:137 @@ -3224,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 898520fa..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 c5eb0fab..1340b87f 100644 --- a/cps/translations/fr/LC_MESSAGES/messages.po +++ b/cps/translations/fr/LC_MESSAGES/messages.po @@ -22,604 +22,648 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n > 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistiques" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Reconnecté avec succès" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Commande inconnue" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Page admin" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuration principale" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuration de l’interface utilisateur" -#: cps/admin.py:289 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:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "L'utilisateur n'a pas été trouvé" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} utilisateurs supprimés avec succès" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Demande malformée" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "L’invité ne peut pas avoir ce rôle" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Rôle invalide" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "L’invité ne peut pas avoir cette vue" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Vue invalide" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Aucun paramètre régional valide n’est donné" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Aucune langue de livre valide donnée" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Paramètre non trouvé" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Colonne de lecture non valide" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Colonne restreinte non valide" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuration de Calibre-Web mise à jour" -#: cps/admin.py:591 +#: 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:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Voulez-vous vraiment supprimer ce domaine ?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Voulez-vous vraiment supprimer cet utilisateur ?" -#: cps/admin.py:597 +#: 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:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 +#: 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: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:764 -msgid "Tag not found" -msgstr "Étiquette introuvable" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Action invalide" - -#: cps/admin.py:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} entrées de synchronisation supprimées" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Étiquette introuvable" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Action invalide" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Veuillez entrer un compte de service LDAP" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Erreur de la base de données: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "La base de données n'est pas accessible en écriture" - -#: cps/admin.py:1266 -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:1270 -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:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Les paramètres du serveur de courriels ont été mis à jour" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Configuration des options" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Veuillez compléter tous les champs !" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "Cette adresse de courriel n’appartient pas à un domaine valide" - -#: cps/admin.py:1416 cps/admin.py:1576 -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:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Utilisateur '%(user)s' créé" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Un compte existant a été trouvé pour cette adresse de courriel ou pour ce surnom." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Utilisateur '%(nick)s' supprimé" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "Impossible de supprimer l’utilisateur Invité" - -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Aucun utilisateur admin restant, impossible de supprimer l’utilisateur" +#: 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:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Éditer l'utilisateur %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Utilisateur '%(nick)s' mis à jour" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Une erreur inconnue est survenue. Veuillez réessayer plus tard." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Modifier les paramètres du serveur de courriels" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "La vérification du compte Gmail réussie" +msgid "Oops! Database Error: %(error)s." +msgstr "Erreur de la base de données: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Veuillez d'abord configurer votre adresse de courriel..." -#: cps/admin.py:1637 -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:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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 "Une erreur inconnue est survenue. Veuillez réessayer plus tard." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Éditer l'utilisateur %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visualiseur de fichier journal" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Demande de mise à jour" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Téléchargement de la mise à jour" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Décompression de la mise à jour" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Remplacement des fichiers" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Les connexions à la base de données ont été fermées" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Arrêt du serveur" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Erreur de connexion" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Erreur générale" -#: cps/admin.py:1773 +#: 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:1774 +#: 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:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Erreur : %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} utilisateur importé avec succès" -#: cps/converter.py:30 -msgid "not installed" -msgstr "non installé" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Les permissions d'exécutions manquantes" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "La base de données n'est pas accessible en écriture" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "La colonne personnalisée No.%(column)d n'existe pas dans la base de données calibre" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Aucun" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Le format du livre a été supprimé avec succès" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Le livre a été supprimé avec succès" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "Les paramètres du serveur de courriels ont été mis à jour" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "Vous n’avez par les permissions pour supprimer les livres" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Configuration des options" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Veuillez compléter tous les champs !" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "modifier les métadonnées" +#: 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:1909 +msgid "Add new user" +msgstr "Ajouter un nouvel utilisateur" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s n’est pas un nombre valide, ignoré" +msgid "User '%(user)s' created" +msgstr "Utilisateur '%(user)s' créé" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s n'est pas une langue valide" +#: cps/admin.py:1926 +#, fuzzy +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/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Utilisateur '%(nick)s' supprimé" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Impossible de supprimer l’utilisateur Invité" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Utilisateur '%(nick)s' mis à jour" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Pour être déposé le fichier doit avoir une extension" +#: cps/converter.py:31 +msgid "not installed" +msgstr "non installé" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Impossible de créer le chemin %(path)s (Permission refusée)." +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Les permissions d'exécutions manquantes" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Échec de la sauvegarde du fichier %(file)s." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Le format de fichier %(ext)s a été ajouté à %(book)s" +#: 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 "Aucun" + +#: 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:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Les métadonnées ont bien été mises à jour" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Le fichier %(file)s a été téléchargé" + +#: 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: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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: 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:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Le livre a été supprimé avec succès" + +#: 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:943 +msgid "edit metadata" +msgstr "modifier les métadonnées" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Le fichier %(file)s a été téléchargé" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s n’est pas un nombre valide, ignoré" -#: cps/editbooks.py:1143 -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:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, 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" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Impossible de créer le chemin %(path)s (Permission refusée)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, 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" +msgid "Failed to store file %(file)s." +msgstr "Échec de la sauvegarde du fichier %(file)s." + +#: 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" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -634,187 +678,184 @@ msgstr "Le domaine de retour d’appel (Callback domain) est non vérifié, veui 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Envoyer vers Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Courriel de test" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Bien démarrer avec Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Envoyer %(format)s vers le Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Envoyer vers Kindle" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Cet utilisateur est déjà pris" -#: cps/helper.py:669 -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:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Erreur lors du téléchargement de la couverture" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Erreur de format de couverture" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Impossible de créer le chemin pour la couverture" -#: cps/helper.py:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Contenu du fichier de couverture invalide" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Fichier binaire Unrar non trouvé" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Une erreur est survenue lors de l'exécution d'UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "En attente" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Echoué" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Débuté" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Terminé" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Découvrir" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Statut inconnu" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuration Kobo" @@ -823,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:1613 +#: 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 @@ -884,12 +925,13 @@ msgstr "Erreur Oauth Google, veuillez réessayer plus tard." msgid "Google Oauth error: {}" msgstr "Erreur Oauth Google : {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Étoiles" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -905,497 +947,619 @@ msgstr "Jeton expiré" msgid "Success! Please return to your device" msgstr "Réussite! Merci de vous tourner vers votre appareil" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Livres" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Afficher les livres récents" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Montrer les livres populaires" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Livres téléchargés" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Afficher non-lus" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Découvrir" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Notes" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Livres archivés" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Liste des livres" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Chercher" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Publié après le " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publié avant le " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Évaluation <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Évaluation >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Status de lecture = %(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Recherche avancée" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "L’étagère indiquée est invalide" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Désolé, vous n’êtes pas autorisé à ajouter un livre dans l’étagère: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Ce livre est déjà sur l’étagère : %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Le livre a bien été ajouté à l'étagère : %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "Vous n’êtes pas autorisé à ajouter un livre à l’étagère" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Ces livres sont déjà sur l’étagère : %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Les livres ont été ajoutés à l’étagère : %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Impossible d’ajouter les livres à l’étagère : %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Le livre a été supprimé de l'étagère %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 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:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Créer une étagère" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Désolé, vous n’êtes pas autorisé à enlever un livre de cette étagère : %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Modifier une étagère" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Le livre a été supprimé avec succès" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Modifier l’arrangement de l’étagère : ‘%(name)s’" + +#: 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:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Étagère %(title)s créée" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "L’étagère %(title)s a été modifiée" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Il y a eu une erreur" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Le livre a été supprimé avec succès" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Modifier l’arrangement de l’étagère : ‘%(name)s’" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Étagère : '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Tâches" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "En attente" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Echoué" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Débuté" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Terminé" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Statut inconnu" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Données inattendues lors de la lecture des informations de mise à jour" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Aucune mise à jour disponible. Vous avez déjà la dernière version installée" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Une nouvelle mise à jour est disponible. Cliquez sur le bouton ci-dessous pour charger la dernière version." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Impossible d'extraire les informations de mise à jour" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Téléchargez la dernière version en cliquant sur le bouton ci-dessous." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Une nouvelle mise à jour est disponible. Cliquez sur le bouton ci-dessous pour charger la version: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Aucune information concernant cette version n’est disponible" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Découvrir (Livres au hasard)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Livres populaires (les plus téléchargés)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Livres téléchargés par %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Auteur : %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Éditeur : '%(name)s'" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Séries : %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Évaluation : %(rating)s étoiles" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Format de fichier : %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Catégorie : %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Langue : %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Recherche avancée" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Chercher" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Téléchargements" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Liste des évaluations" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Liste de formats de fichiers" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Tâches" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Publié après le " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Publié avant le " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Évaluation <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Évaluation >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Status de lecture = %(status)s" - -#: cps/web.py:1425 -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/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:1527 +#: cps/web.py:1240 #, 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" +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:1531 +#: 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 "Il y a eu une erreur en envoyant ce livre : %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Impossible d’activer l’authentification LDAP" -#: cps/web.py:1621 -#, 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:1627 -#, 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:1631 cps/web.py:1656 +#: 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:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "ebook-convert calibre %(tool)s non trouvé" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "Format %(format)s non trouvé sur le disque" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "Le convertisseur Ebook a échoué avec une erreur inconnue" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "La commande Kepubify-converter a échouée : %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Fichier converti non trouvé ou plus d'un fichier dans le chemin %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "La commande ebook-convert a échouée : %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre a échoué avec l’erreur : %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "modifier les métadonnées" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Téléverser" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Liste des utilisateurs" @@ -1408,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Envoyer vers une adresse de courriel Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Administration" @@ -1425,13 +1590,8 @@ msgstr "Administration" msgid "Password" msgstr "Mot de passe" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Téléverser" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1445,7 +1605,7 @@ msgstr "Afficher les livres" msgid "Edit" msgstr "Éditer" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1456,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 @@ -1486,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 @@ -1558,78 +1715,109 @@ msgstr "Éditer la configuration principale" msgid "Edit UI Configuration" msgstr "Éditer la configuration de l’interface utilisateur" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Administration" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Télécharger le package de débogage" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Afficher les fichiers journaux" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Reconnecter la base de données Calibre" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Redémarrer Calibre-Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Arrêter Calibre-Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Mise à jour de Calibre-Web" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Détails" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Version actuelle" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Rechercher les mises à jour" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Effectuer la mise à jour" -#: cps/templates/admin.html:210 +#: 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:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: 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:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Mise à jour en cours, ne pas rafraîchir la page" @@ -1641,39 +1829,39 @@ msgstr "via" msgid "In Library" msgstr "Dans la librairie" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Trier en fonction de la date du livre, le plus récent en premier" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Trier en fonction de la date du livre, le plus ancien en premier" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Trier les titres dans l’ordre alphabétique" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Trier le titre dans l’ordre alphabétique inverse" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Trier en fonction de la date de publication, le plus récent en premier" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Trier en fonction de la date de publication, le plus ancien en premier" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "réduire" @@ -1681,165 +1869,166 @@ msgstr "réduire" msgid "More by" msgstr "Plus de" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Supprimer le livre" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Supprimer les formats :" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Convertir le format du livre :" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Convertir depuis :" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "choisir une option" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Convertir vers :" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Convertir le livre" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Titre du livre" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Auteur" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Description" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identifiants" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Type d'identifiant" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Valeur d'identifiant" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Supprimer" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Ajouter un identifiant" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Étiquettes" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID de séries" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Évaluation" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Obtenir la couverture à partir d'une URL (JPEG - l'image sera téléchargée et sauvegardée dans la base de données)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Téléverser la couverture depuis un fichier en local" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Date de publication" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Éditeur" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Format du fichier téléversé" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Voir le livre lors de la sauvegarde" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Obtenir les métadonnées" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Sauvegarder" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Mot-clé" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Rechercher le mot-clé " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Cliquer sur la couverture pour importer les métadonnées dans le formulaire" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Chargement..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Source" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Erreur lors de la recherche!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Aucun résultat. Veuillez essayer avec un nouveau mot clé." @@ -1932,7 +2121,7 @@ msgid "Comments" msgstr "Commentaires" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1948,6 +2137,7 @@ msgid "Enter " msgstr "Identifiants" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Êtes-vous vraiment sûr?" @@ -2053,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 @@ -2069,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 @@ -2259,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" @@ -2271,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" @@ -2362,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lire dans le navigateur" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Écouter dans le navigateur" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publié" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marquer comme non lu" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marquer comme lu" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Lu" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restaurer à partir de l'archive" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Ajouter comme archive" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivé" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Description :" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2458,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:29 +#: 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" @@ -2487,188 +2728,196 @@ 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:170 +#: 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 msgid "Kobo Token:" msgstr "Jeton de synchro Kobo" -#: cps/templates/http_error.html:31 +#: 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 "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" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "Trier de manière ascendante selon le nombre de téléchargements" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "Trier de manière descendante selon le nombre de téléchargements" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Trier les auteurs dans l’ordre alphabétique" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Trier les auteurs dans l’ordre alphabétique inverse" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Trier par ordre croissant en fonction de l’index de série" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Accueil" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Basculer la navigation" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Chercher dans librairie" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Compte" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Déconnexion" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Téléversement en cours..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Erreur" -#: cps/templates/layout.html:63 +#: 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:76 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 "Paramètres" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Compte" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Déconnexion" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Veuillez ne pas rafraîchir la page" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Explorer" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "À propos" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Précédent" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Détails du livre" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Se rappeler de moi" @@ -2677,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" @@ -2773,7 +3022,7 @@ msgstr "Répertoire parent" msgid "Select" msgstr "Sélectionner" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Livre" @@ -2787,128 +3036,162 @@ msgstr "Catalogue de livres électroniques Calibre-Web" msgid "epub Reader" msgstr "Lecteur PDF" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Clair" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Sombre" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Retour" + +#: 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:116 -msgid "Light" -msgstr "Clair" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Sombre" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Page admin" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2917,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" @@ -2936,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 @@ -2955,15 +3238,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Aucun résultat trouvé" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Chercher le terme:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Résultats pour :" @@ -2975,64 +3262,72 @@ 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" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Supprimer cette étagère" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Éditer les propriétés de l’étagère" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Organiser les livres manuellement" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Désactiver l’ordre de modification" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Activer l’ordre de modification" @@ -3077,8 +3372,8 @@ msgid "System Statistics" msgstr "Statistiques système" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Bibliothèque logicielle" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3104,9 +3399,17 @@ 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 "" + +#: 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" @@ -3172,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Envoyer vers une adresse de courriel Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Courriel de test" #: cps/templates/user_table.html:137 @@ -3253,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 new file mode 100644 index 00000000..40b996e9 Binary files /dev/null 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 new file mode 100644 index 00000000..ffca5448 --- /dev/null +++ b/cps/translations/gl/LC_MESSAGES/messages.po @@ -0,0 +1,3496 @@ +# Translation to Galician for Calibre-Web. +# pollitor , 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: 2022-08-11 16:46+0200\n" +"Last-Translator: pollitor \n" +"Language: gl\n" +"Language-Team: gl\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, recargue a páxina" + +#: 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:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 +msgid "Unknown command" +msgstr "Orde descoñecida" + +#: cps/admin.py:173 +#, fuzzy +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: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:231 +msgid "Admin page" +msgstr "Páxina de administración" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Configuración Básica" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "Configuración da Interface de Usuario" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Editar Usuarios" + +#: 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:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Usuario non atopado" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "{} usuarios borrados con éxito" + +#: 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:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Petición mal formada" + +#: 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:482 +msgid "Guest can't have this role" +msgstr "O convidado non pode ter este rol" + +#: 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: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:500 +msgid "Invalid role" +msgstr "Rol non válido" + +#: cps/admin.py:504 +msgid "Guest can't have this view" +msgstr "O convidado non pode ter esta vista" + +#: cps/admin.py:514 +msgid "Invalid view" +msgstr "Vista non válida" + +#: 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:521 +msgid "No Valid Locale Given" +msgstr "Non hai unha localización válida" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Non se indicou unha lingua válida para o libro" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Parámetro non atopado" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Columna de lectura non válida" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Columna restrinxida non válida" + +#: cps/admin.py:597 cps/admin.py:1848 +msgid "Calibre-Web configuration updated" +msgstr "Configuración de Calibre-Web actualizada" + +#: 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:611 +msgid "Do you really want to delete this domain?" +msgstr "De verdade desexas borrar este dominio?" + +#: cps/admin.py:613 +msgid "Do you really want to delete this user?" +msgstr "De verdade queres borrar este usuario?" + +#: cps/admin.py:615 +msgid "Are you sure you want to delete this shelf?" +msgstr "De verdade queres eliminar este andel?" + +#: 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: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: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: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: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: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: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: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: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: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: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 "Elimináronse {} entradas de sincronización" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Etiqueta non atopada" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Acción non válida" + +#: 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: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: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: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: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:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "Por favor, introduce unha conta de servizo LDAP" + +#: 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:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "O LDAP Group Object Filter ten parénteses que non casan" + +#: 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:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "O LDAP Group Object Filter ten parénteses que non casan" + +#: 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: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: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:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Engadir novo usuario" + +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Cambiar os parámetros do correo" + +#: 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 "Error na base de datos: %(error)s." + +#: 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: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:1328 +msgid "Please configure your e-mail address first..." +msgstr "Por favor, configure o seu correo electrónico primeiro..." + +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Actualizáronse os axustes do servidor de correo electrónico" + +#: 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:1365 +msgid "Invalid start time for task specified" +msgstr "Indicada unha hora incorrecta de comezo de tarefa" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Indicada unha duracción incorrecta para a tarefa" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Actualizouse a configuración das tarefas programadas" + +#: 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:1394 +msgid "Settings DB is not Writeable" +msgstr "A configuración da DB non se pode escribir" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Editar o Usuario %(nick)s" + +#: 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:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Configura primeiro os parámetros do servidor SMTP..." + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "Visor do ficheiro de rexistro" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "Solicitando paquete de actualización" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "Descargando paquete de actualización" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "Descomprimendo paquete de actualización" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "Remplazando archivos" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "As conexións coa base datos están pechadas" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "Detendo o servidor" + +#: 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: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: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 conexión" + +#: 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:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Erro xeral" + +#: 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:1531 +msgid "Files could not be replaced during update" +msgstr "Non se puideron substituír os ficheiros durante a actualización" + +#: 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:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "Erro ao crear polo menos un usuario 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: o servidor LDAP non devolveu ningún usuario" + +#: 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:1652 +msgid "{} User Successfully Imported" +msgstr "Usuario {} importado con éxito" + +#: 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:1730 +msgid "DB is not Writeable" +msgstr "A base de datos non é modificable" + +#: 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: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: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:1879 +msgid "Database Configuration" +msgstr "Configuración da base de datos" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Por favor, cubra todos os campos!" + +#: 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: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: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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Usuario '%(nick)s' eliminado" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Non se pode borrar ao Usuario Invitado" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Usuario '%(nick)s' actualizado" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "non instalado" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Faltan permisos de execución" + +#: 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: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 "Ningún" + +#: 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: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: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:226 +msgid "Metadata successfully updated" +msgstr "Metadatos actualizados con éxito" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "Erro editando libro: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "O ficheiro %(file)s subiuse" + +#: 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: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: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: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: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: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: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: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: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:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Formato de libro eliminado con éxito" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Libro eliminado con éxito" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Vostede non ten permisos para borrar libros" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "editar metadatos" + +#: 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: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: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:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "Fallo ao gardar o arquivo %(file)s." + +#: 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" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "A configuración de Google Drive non se completou, intente desactivar e activar Google Drive outra vez" + +#: cps/gdrive.py:95 +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: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: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:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s non atopado: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" +msgstr "Enviar ao Kindle" + +#: 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:115 +#, fuzzy +msgid "Calibre-Web Test Email" +msgstr "Correo de proba de Calibre-Web" + +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" +msgstr "Comprobar correo electrónico" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Primeiros pasos con Calibre-Web" + +#: 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: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: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:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "Enviar ao Kindle %(book)s" + +#: 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:342 +msgid "Read status could not set: {}" +msgstr "O estado de lectura non pode fixarse: {}" + +#: 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:371 +#, python-format +msgid "Deleting book %(id)s failed: %(message)s" +msgstr "O borrado do libro %(id)s fallou: %(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 "Borrando o libro %(id)s, a ruta de libro non é válida: %(path)s" + +#: 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: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: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:582 +msgid "Error in rename file in path: {}" +msgstr "Erro ao renomear o ficheiro na ruta: {}" + +#: 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:665 +msgid "Found an existing account for this Email address" +msgstr "" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Este nome de usuario xa está en uso" + +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "Enderezo de correo non vá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' non está instalado pero se necesita para as cargas de cubertas" + +#: cps/helper.py:862 +msgid "Error Downloading Cover" +msgstr "Erro ao descargar a cuberta" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Erro no formato da cuberta" + +#: 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:878 +msgid "Failed to create path for cover" +msgstr "Erro ao crear unha ruta para a cuberta" + +#: 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: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:917 +msgid "Invalid cover file content" +msgstr "Contido do arquivo de cuberta non válido" + +#: 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:973 +msgid "Unrar binary file not found" +msgstr "Non se atopa o arquivo binario de UnRar" + +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "Erro executando UnRar" + +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Descubrir" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" + +#: 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:116 +msgid "Kobo Setup" +msgstr "Configuración de Kobo" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "Rexistrado con %(provider)s" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "Iniciou sesión como : '%(nickname)s'" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "O enlace a %(oauth)s realizouse con éxito" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "Acceso errado, ningún usuario enlazado coa conta OAuth" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "%(oauth)s desenlazado con éxito" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "Erro ao desenlazar %(oauth)s" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "Non vinculado con %(oauth)s" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Erro ao iniciar sesión con GitHub." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Erro ao obter a información do usuario de GitHub." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Erro ao iniciar sesión con Google." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Erro ao obter información do usuario de Google." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "Erro en GitHub Oauth, por favor, volva a intentalo máis tarde." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "Erro GitHub Oauth {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Erro en Google Oauth, por favor volva a intentalo máis tarde." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Erro Google Oauth {}" + +#: 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 "Inicio de sesión" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Token non atopado" + +#: 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 "Correcto! Por favor volte ao seu dispositivo" + +#: cps/render_template.py:42 cps/web.py:414 +msgid "Books" +msgstr "Libros" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Mostrar libros recentes" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Libros populares" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Mostrar libros populares" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Libros descargados" + +#: 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:59 cps/templates/index.xml:33 cps/web.py:429 +msgid "Top Rated Books" +msgstr "Libros mellor valorados" + +#: 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: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:64 +#, fuzzy +msgid "Show Read and Unread" +msgstr "Mostrar lidos e non lidos" + +#: 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:68 +msgid "Show unread" +msgstr "Mostrar non lidos" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Descubrir" + +#: 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: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:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" +msgstr "Mostrar selección de categorías" + +#: 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:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Mostrar selección de series" + +#: 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 selección de autores" + +#: 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:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Mostrar selección de editores" + +#: 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:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" +msgstr "Mostrar selección de linguas" + +#: cps/render_template.py:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Valoracións" + +#: 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:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Formatos de arquivo" + +#: 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:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Libros arquivados" + +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Mostrar libros arquivados" + +#: cps/render_template.py:101 cps/web.py:807 +msgid "Books List" +msgstr "Lista de libros" + +#: 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: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 "Buscar" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Publicado despóis de " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publicado antes de " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Valoración <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Valoración >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Estado de lectura = %(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Búsqueda avanzada" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "Andel especificado non válido" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Sentímolo, non ten permisos para engdir un libro ao andel: %(shelfname)s" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "O libro xa forma parte do andel: %(shelfname)s" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "O libro engadiuse ao andel: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "Non ten permiso para engadir un libro ao andel" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "Os libros xa forman parte do andel: %(name)s" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "Os libros engadíronse ao andel: %(sname)s" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "Non se pudideron engadir libros ao andel: %(sname)s" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "O libro eliminouse do andel: %(sname)s" + +#: cps/shelf.py:200 +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:157 +msgid "Create a Shelf" +msgstr "Crear un andel" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Síntoo, non ten permiso para editar o andel: %(sname)s" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Editar un andel" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Erro borrando o estante" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Andel eliminado con éxito" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Cambiar a orde do andel: '%(name)s'" + +#: 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:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Andel %(title)s creado" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Andel %(title)s cambiado" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "Ocorreu un erro" + +#: 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: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:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Andel: '%(name)s'" + +#: 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:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Tarefas" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Esperando" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Fallou" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Comezado" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Rematado" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Rematado" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Cancelado" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Estado descoñecido" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "Dato inesperado mentres líase a información de actualización" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "Actualización non dispoñiible. Xa tes instalada a versión máis recente" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "Unha nova actualización está dispoñible. Preme no botón inferior para actualizar á versión máis reciente." + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "Non se pode conseguir información sobre a actualización" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "Preme no botón de abaixo para actualizar á última versión estable." + +#: 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 "Hai unha nova actualización dispoñible. Preme no botón de abaixo para actualizar á versión: %(version)s" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "Non hai información do lanzamento dispoñible" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "Descubrir (Libros ao chou)" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "Libros populares (os máis descargados)" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "Libros descargados por %(user)s" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "Autor/es: %(name)s" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "Editor/es: %(name)s" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "Series: %(serie)s" + +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Valoración: Ningunha" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "Valoración: %(rating)s estrelas" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "Formato do arquivo: %(format)s" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "Categoría: %(name)s" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Lingua: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Descargas" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Lista de valoracións" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Lista de formatos" + +#: 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:1240 +#, python-format +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: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: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 "Rexistro" + +#: 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: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:1348 cps/web.py:1366 +#, fuzzy +msgid "Cannot activate LDAP authentication" +msgstr "Non se pode activar a autenticación 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 "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:1388 +#, fuzzy, python-format +msgid "Could not login: %(message)s" +msgstr "Non se puido entrar: %(message)s" + +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy +msgid "Wrong Username or Password" +msgstr "Usuario ou contrasinal no válido" + +#: 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: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:1413 +#, fuzzy, python-format +msgid "You are now logged in as: '%(nickname)s'" +msgstr "Iniciou sesión 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 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" +msgstr "Non se atopou Calibre ebook-convert %(tool)s" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "O formato %(format)s non se atopou no disco" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "O conversor de Ebook fallou cun erro descoñecido" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "Kepubify-converter fallou: %(error)s" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "Arquivo convertido non atopado, ou máis dun arquivo no directorio %(folder)s" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "Fallou Ebook-converter: %(error)s" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "Calibre fallou co erro: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Convertir" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Reconectando a base de datos de Calibre" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "Correo electrónico" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "editar metadatos" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "Xeradas %(count)s miniaturas de cubertas" + +#: 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:289 +msgid "Generated {0} series thumbnails" +msgstr "Xeradas {0} miniaturas de series" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Subir arquivo" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Usuarios" + +#: 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 usuario" + +#: 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 "Enderezo de correo electrónico" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +msgid "Send to eReader Email" +msgstr "Enviar ao enderezo de correo electrónico do Kindle" + +#: cps/templates/admin.html:17 cps/templates/layout.html:91 +#: cps/templates/user_table.html:143 +msgid "Admin" +msgstr "Administrador" + +#: cps/templates/admin.html:18 cps/templates/login.html:13 +#: cps/templates/login.html:14 cps/templates/user_edit.html:23 +msgid "Password" +msgstr "Contrasinal" + +#: 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" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Ver libros" + +#: 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 "Borrar" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Andel público" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "Importar usuarios LDAP" + +#: cps/templates/admin.html:62 +msgid "Email Server Settings" +msgstr "Axustes do servidor de correo electrónico" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "Servidor SMTP" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "Porto SMTP" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "Cifraxe" + +#: 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 "Dende o correo electrónico" + +#: cps/templates/admin.html:90 +#, fuzzy +msgid "Email Service" +msgstr "Servizo de correo electrónico" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "Gmail por Oauth2" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Configuración" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Directorio da base de datos de Calibre" + +#: cps/templates/admin.html:113 cps/templates/config_edit.html:68 +msgid "Log Level" +msgstr "Nivel de rexistro" + +#: cps/templates/admin.html:117 +msgid "Port" +msgstr "Porto" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "Porto externo" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Libros por páxina" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Cargas" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Navegación anónima" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Rexistro público" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Acceso remoto mediante enlace máxico" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "Acceso mediante Proxy inverso" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "Nome de cabeceira do Proxy inverso" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Editar a configuración da base de datos de Calibre" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Editar a configuración básica" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Editar a configuración da interfaz de usuario" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Tarefas programadas" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: 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 Duration" +msgstr "Duración máxima das tarefas" + +#: 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/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Reconectar á librería de Calibre" + +#: 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:203 +msgid "Administration" +msgstr "Administración" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Descargar o paquete de depuración" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Ver arquivos de rexistro" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Reiniciar" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Apagar" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Información de versión" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Versión" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Detalles" + +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Versión actual" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Comprobar actualizacións" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Realizar actualización" + +#: cps/templates/admin.html:253 +msgid "Are you sure you want to restart?" +msgstr "De verdade queres 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 "Vale" + +#: 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 "De verdade quere deter?" + +#: cps/templates/admin.html:283 +msgid "Updating, please do not reload this page" +msgstr "Actualizando. Por favor, non recargue a páxina" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "via" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "Na Librería" + +#: 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 "Ordear pola data do libro, máis 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 "Ordear pola data do libro, máis 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 "Ordear polo título en orden alfabético" + +#: 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 "Ordear polo título en orde alfabético invertido" + +#: 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 "Ordear pola data de publicación, máis recente 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 "Ordear pola data de publicación, máis 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 "reducir" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Máis de" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Borrar libro" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Borrar formatos:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "Convertir formato de libro:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Convertir dende:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "seleccionar unha opción" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Convertir a:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Convertir libro" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Título do libro" + +#: 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 "Descrición" + +#: 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 de identificador" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Borrar" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Engadir 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 "ID de serie" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Valoración" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Obter portada de URL (JPEG, a portada descargarase e almacenarase na base de datos)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Cargar portada dende un disco local" + +#: cps/templates/book_edit.html:113 +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: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: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:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Sí" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Non" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Cargar formato" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Ver libro ao gardar" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Obter metadatos" + +#: 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 "Gardar" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Palabra chave" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Buscar por palabras chave " + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Premer na portada para cargar los metadatos no formulario" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "Cargando..." + +#: 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" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Orixe" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Erro na busca!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Non se atoparon resultados! Por favor intenta con outra palabra 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 é necesario" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Unir libros seleccionados" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Eliminar selección" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Intercambiar autor e título" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Actualizar orde do título automáticamente" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Actualizar orde do autor automáticamente" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Introduce 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 "Introduce a orde do título" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Orde do título" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Introduce orde do autor" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Orde do autor" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Introduce os autores" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Introduce as categorías" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Introduce as series" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Índice da serie" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Introduce as linguas" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Data de publicación" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Introduce os Editores" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Introducir os comentarios" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Comentarios" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "Estado do arquivo" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Leer estado" + +#: 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 "Introduce " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "De verdade estás seguro?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "Libros co título uniranse de:" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "No libro co título:" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Unir" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Localización da base de datos 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 Google Drive" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Carpeta de Google Drive para Calibre" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "Metadata Watch Channel ID" + +#: 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 "A localización da base de datos non é válida. Por favor, Introduce a ruta correcta" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Configuración do servidor" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Porto do servidor" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "Localización do arquivo de certificado SSL (deixar en branco se non hai un servidor SSL)" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "Localización do arquivo clave SSL (dejar en blanco si no hay un servidor SSL)" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "Canle de actualización" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "Estable" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "Nocturno" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "Anfitrións de confianza (Separados por comas)" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "Configuración do arquivo de rexistro" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "Localización e nome do arquivo de rexistro (se non se especifica será calibre-web.log)" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "Habilitar rexistro de acceso" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "Localización e nombre do archivo de rexistro de acceso (access.log non ten ningunha entrada)" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "Configuración de características" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "Convertir caracteres non ingleses no título e no autor mentres se graba no disco" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "Permitir cargas" + +#: cps/templates/config_edit.html:108 +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 +msgid "Allowed Upload Fileformats" +msgstr "Formatos de arquivo permitidos para carga" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "Permitir navegación anónima" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "Permitir rexistro público" + +#: cps/templates/config_edit.html:127 +msgid "Use Email as Username" +msgstr "Utilizar correo electrónico como nome de usuario" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "Permitir inicio de sesión remoto (\"magic link\")" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "Activar a sincronización con Kobo" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "Peticións proxy á tenda Kobo descoñecidas" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "Porto externo do servidor (para peticións API)" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Usar Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Obter unha API Key" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Goodreads API Key" + +#: 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 "Permitir Autenticación Proxy Inversa" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Tipo de inicio de sesión" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "Usar autenticación estándar" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "Usar autenticación 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 de anfitrión ou enderezo IP do servidor LDAP" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "Porto do servidor LDAP" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "Cifrado 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 "Ruta LDAP CACertificate (So necesaria para certificado de autenticación de cliente)" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "Ruta LDAP Certificate (So necesaria para certificado de autenticación de cliente)" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "Ruta LDAP Keyfile (So necesaria para certificado de autenticación de cliente)" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "Autenticación LDAP" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "Anónimo" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "Non autenticado" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "Simple" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "Nome de usuario de administrador LDAP" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "Contrasinal de administrador LDAP" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "Nome distinguido LDAP (DN)" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "Filtro de obxectos de usuario 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 configuracións son necesarias para a importación de usuarios" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "Filtro de obxectos de grupo LDAP" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "Nome de grupo LDAP" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "Campo de membros de grupo LDAP" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "Filtro de detección LDAP Member User" + +#: cps/templates/config_edit.html:280 +msgid "Autodetect" +msgstr "Auto detectar" + +#: 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 LDAP Member User" + +#: cps/templates/config_edit.html:297 +#, python-format +msgid "Obtain %(provider)s OAuth Credential" +msgstr "Obter a Credencial OAuth de %(provider)s" + +#: cps/templates/config_edit.html:300 +#, python-format +msgid "%(provider)s OAuth Client Id" +msgstr "Id de cliente de OAuth de %(provider)s" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "Secreto OAuth de Cliente de %(provider)s" + +#: cps/templates/config_edit.html:320 +msgid "External binaries" +msgstr "Binarios externos" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "Ruta para Calibre E-Book Converter" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "Axustes de Calibre E-Book Converter" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "Ruta para Kepubify E-Book Converter" + +#: cps/templates/config_edit.html:345 +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" + +#: cps/templates/config_view_edit.html:32 +msgid "No. of Random Books to Display" +msgstr "Número de libros aleatorios a mostrar" + +#: cps/templates/config_view_edit.html:36 +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:101 +msgid "Theme" +msgstr "Tema" + +#: cps/templates/config_view_edit.html:42 +msgid "Standard Theme" +msgstr "Tema estándar" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "caliBlur! Tema Escuro" + +#: cps/templates/config_view_edit.html:47 +msgid "Regular Expression for Ignoring Columns" +msgstr "Expresión regular para ignorar columnas" + +#: cps/templates/config_view_edit.html:51 +msgid "Link Read/Unread Status to Calibre Column" +msgstr "Enlazar á columna de Calibre de lido/sen ler" + +#: cps/templates/config_view_edit.html:60 +msgid "View Restrictions based on Calibre column" +msgstr "Ver restricións baseadas na columna de Calibre" + +#: cps/templates/config_view_edit.html:69 +msgid "Regular Expression for Title Sorting" +msgstr "Expresión regular para ordear títulos" + +#: cps/templates/config_view_edit.html:80 +msgid "Default Settings for New Users" +msgstr "Axustes por defecto para novos usuarios" + +#: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 +msgid "Admin User" +msgstr "Usuario administrador" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +msgid "Allow Downloads" +msgstr "Permitir descargas" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "Permitir visor de libros" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +msgid "Allow Uploads" +msgstr "Permitir cargas de arquivos" + +#: 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 borrar libros" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "Permitir cambiar a contrasinal" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "Permitir editar andeis públicos" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "Lingua predeterminada" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "Lingua visible predeterminada dos libros" + +#: cps/templates/config_view_edit.html:147 +msgid "Default Visibilities for New Users" +msgstr "Visibilidade predeterminada para novos usuarios" + +#: 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 libros aleatorios na vista detallada" + +#: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 +msgid "Add Allowed/Denied Tags" +msgstr "Engadir etiquetas Permitidas/denegados" + +#: cps/templates/config_view_edit.html:167 +msgid "Add Allowed/Denied custom column values" +msgstr "Engadir valores personalizados Permitidos/denegados" + +#: 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 "Escoitar no navegador" + +#: 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:201 cps/templates/listenmp3.html:111 +msgid "Published" +msgstr "Publicado" + +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 +msgid "Mark As Unread" +msgstr "Marcar como non 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 dende o arquivo" + +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "Engadir a arquivo" + +#: 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 "Descrición:" + +#: 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: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 metadatos" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "Escolle tipo de servidor" + +#: cps/templates/email_edit.html:15 +#, fuzzy +msgid "Standard Email Account" +msgstr "Usar conta de correo electrónico estándar" + +#: cps/templates/email_edit.html:16 +#, fuzzy +msgid "Gmail Account" +msgstr "Escolle tipo de servidor" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "Revogar acceso a 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 "Contrasinal SMTP" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "Tamaño límite do arquivo achegado" + +#: cps/templates/email_edit.html:66 +#, 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: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 "Dominios permitidos para rexistrarse" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "Engadir dominio" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "Engadir" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +msgid "Enter domainname" +msgstr "Introducir nome de dominio" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "Dominios prohibidos (Blaclist)" + +#: 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 "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:" +msgstr "Token de sincronización de 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 "A instancia de Calibre-Web non está configurada, por favor contacta co teu administrador" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "Crear una incidencia" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "Voltar ao inicio" + +#: cps/templates/http_error.html:53 +msgid "Logout User" +msgstr "Pechar sesión" + +#: cps/templates/index.html:71 +msgid "Sort ascending according to download count" +msgstr "Ordear carra arriba segundo a conta de descargas" + +#: cps/templates/index.html:72 +msgid "Sort descending according to download count" +msgstr "Ordear cara abaixo segundo a conta de descargas" + +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "Ordenar autores en orde 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 en orde alfabética reversa" + +#: cps/templates/index.html:83 +msgid "Sort ascending according to series index" +msgstr "Ordear cara arriba segundo ao índice de serie" + +#: cps/templates/index.html:84 +msgid "Sort descending according to series index" +msgstr "Ordear cara abaixo segundo ao índice de serie" + +#: cps/templates/index.xml:7 +msgid "Start" +msgstr "Comezar" + +#: cps/templates/index.xml:19 +msgid "Alphabetical Books" +msgstr "Libros alfabéticos" + +#: cps/templates/index.xml:23 +msgid "Books sorted alphabetically" +msgstr "Libros ordeados alfabéticamente" + +#: 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: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:40 +msgid "Recently added Books" +msgstr "Libros engadidos recentemente" + +#: cps/templates/index.xml:44 +msgid "The latest Books" +msgstr "Últimos libros" + +#: cps/templates/index.xml:47 +msgid "Random Books" +msgstr "Libros ao chou" + +#: cps/templates/index.xml:74 +msgid "Books ordered by Author" +msgstr "Libros ordeados por autor" + +#: cps/templates/index.xml:81 +msgid "Books ordered by publisher" +msgstr "Libros ordeados por editor" + +#: cps/templates/index.xml:88 +msgid "Books ordered by category" +msgstr "Libros ordeados por categorías" + +#: cps/templates/index.xml:95 +msgid "Books ordered by series" +msgstr "Libros ordeados por series" + +#: cps/templates/index.xml:102 +msgid "Books ordered by Languages" +msgstr "Libros ordeados por lingua" + +#: cps/templates/index.xml:109 +msgid "Books ordered by Rating" +msgstr "Libros ordeados por valoración" + +#: cps/templates/index.xml:117 +msgid "Books ordered by file formats" +msgstr "Libros ordeados por formato de arquivo" + +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "Andeis" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "Libros organizados en andeis" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "Inicio" + +#: cps/templates/layout.html:32 +msgid "Toggle Navigation" +msgstr "Alternar navegación" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "Buscar na librería" + +#: 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 "Pechar sesión" + +#: 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:145 +msgid "Browse" +msgstr "Navegar" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "Acerca de" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "Previo" + +#: cps/templates/layout.html:199 +msgid "Book Details" +msgstr "Detalles do libro" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Reixa" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "Lembrarme" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "Esqueceu a contrasinal?" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "Iniciar sesión cun enlace máxico" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "Mostrar o rexistro de Calibre-Web: " + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "Rexistro de Calibre-Web: " + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "A saída do fluxo non se pode mostrar" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "Mostrar rexistro de acceso:" + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "Descargar o rexistro de Calibre-Web" + +#: cps/templates/logviewer.html:21 +msgid "Download Access Log" +msgstr "Descargar o rexistro de acceso" + +#: cps/templates/modal_dialogs.html:6 +msgid "Select Allowed/Denied Tags" +msgstr "Seleccionar etiquetas Permitidas/Negadas" + +#: cps/templates/modal_dialogs.html:7 +msgid "Select Allowed/Denied Custom Column Values" +msgstr "Seleccionar valores propios de columnas Permitidas/Denegadas" + +#: cps/templates/modal_dialogs.html:8 +msgid "Select Allowed/Denied Tags of User" +msgstr "Seleccionar etiquetas de usuario Permitido/Denegado" + +#: cps/templates/modal_dialogs.html:9 +msgid "Select Allowed/Denied Custom Column Values of User" +msgstr "Seleccionar columnas personalizadas de usuario Permitido/Denegado" + +#: cps/templates/modal_dialogs.html:15 +msgid "Enter Tag" +msgstr "Introduce a etiqueta" + +#: cps/templates/modal_dialogs.html:24 +msgid "Add View Restriction" +msgstr "Engadir restricción de vista" + +#: cps/templates/modal_dialogs.html:50 +msgid "This book format will be permanently erased from database" +msgstr "Este formato de libro borrarase permanentemente da base de datos" + +#: cps/templates/modal_dialogs.html:51 +msgid "This book will be permanently erased from database" +msgstr "O libro borrarase permanentemente da base de datos" + +#: cps/templates/modal_dialogs.html:52 +msgid "and hard disk" +msgstr "e do disco duro" + +#: cps/templates/modal_dialogs.html:56 +msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." +msgstr "Nota de Kobo importante: os libros eliminados permanecerán nos dispositivos Kobo emparellados." + +#: cps/templates/modal_dialogs.html:57 +msgid "Books must first be archived and the device synced before a book can safely be deleted." +msgstr "Antes de que un libro poida eliminarse con seguridade debe arquivarse e sincronizarse co dispositivo." + +#: cps/templates/modal_dialogs.html:76 +msgid "Choose File Location" +msgstr "Escolla a localización do arquivo" + +#: 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 "tamaño" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "Directorio pai" + +#: cps/templates/modal_dialogs.html:98 +msgid "Select" +msgstr "Seleccionar" + +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 +msgid "Ok" +msgstr "Vale" + +#: cps/templates/osd.xml:5 +msgid "Calibre-Web eBook Catalog" +msgstr "Catálogo de libros electrónicos de Calibre-Web" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "Lector 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 "Oscuro" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sepia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Negro" + +#: 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/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 +msgid "Comic Reader" +msgstr "Lector de Cómics" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "Atallos de teclado" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "Páxina anterior" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +msgid "Next Page" +msgstr "Páxina seguinte" + +#: 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:83 +msgid "Scale to Width" +msgstr "Escalar ao ancho" + +#: cps/templates/readcbr.html:84 +msgid "Scale to Height" +msgstr "Escalar ao alto" + +#: cps/templates/readcbr.html:85 +msgid "Scale to Native" +msgstr "Escalado nativo" + +#: cps/templates/readcbr.html:86 +msgid "Rotate Right" +msgstr "Xirar cara a dereita" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "Xirar cara a esquerda" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "Voltear a imaxe" + +#: 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:122 +msgid "Best" +msgstr "Mellor" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "Ancho" + +#: cps/templates/readcbr.html:124 +msgid "Height" +msgstr "Alto" + +#: cps/templates/readcbr.html:125 +msgid "Native" +msgstr "Nativo" + +#: cps/templates/readcbr.html:130 +msgid "Rotate" +msgstr "Rotar" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "Voltear" + +#: 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 "Dirección" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "De esquerda a dereita" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "De dereita 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 desprazamento" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "Mostrar" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "Agochar" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "Lector DJVU" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "Lector PDF" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "Lector txt" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "Rexistre unha conta nova" + +#: cps/templates/register.html:10 +msgid "Choose a username" +msgstr "Escolla un nome de usuario" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "O teu enderezo de correo" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "Enlace Máxico - Autorizar un novo dispositivo" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "Utiliza otro dispositivo, inicia sesión e visita:" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "Unha vez verificado, iniciará sesión automáticamente neste dispositivo." + +#: cps/templates/remote_login.html:14 +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:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Xerar miniaturas de cubertas de series" + +#: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "Non se atoparon resultados" + +#: cps/templates/search.html:7 +msgid "Search Term:" +msgstr "Termo de busca:" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "Resultados para:" + +#: cps/templates/search_form.html:21 +msgid "Published Date From" +msgstr "Data de publicación dende" + +#: cps/templates/search_form.html:31 +msgid "Published Date To" +msgstr "Data de publicación ata" + +#: 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 series" + +#: cps/templates/search_form.html:96 +msgid "Exclude Shelves" +msgstr "Excluir andeis" + +#: cps/templates/search_form.html:116 +msgid "Exclude Languages" +msgstr "Excluir linguas" + +#: cps/templates/search_form.html:127 +msgid "Extensions" +msgstr "Extensións" + +#: cps/templates/search_form.html:135 +msgid "Exclude Extensions" +msgstr "Excluir extensións" + +#: cps/templates/search_form.html:145 +msgid "Rating Above" +msgstr "Valoración superior a" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "Valoración inferior a" + +#: 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 "Borrar este andel" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "Editar propiedades do andel" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "Ordear libros manualmente" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "Desactivar o cambio de orde" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "Activar o cambio de orde" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "Compartir con todos" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "Sincronizar este andel cun dispositivo Kobo" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "Arrastra para reorganizar a orde" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "Libro agochado" + +#: cps/templates/stats.html:7 +msgid "Library Statistics" +msgstr "Estatísticas da Biblioteca" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "Libros 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 "Categorías nesta biblioteca" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "Series nesta biblioteca" + +#: cps/templates/stats.html:29 +msgid "System Statistics" +msgstr "Estadísticas do sistema" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "Programa" + +#: cps/templates/stats.html:34 +msgid "Installed Version" +msgstr "Versión instalada" + +#: cps/templates/tasks.html:12 +msgid "User" +msgstr "Usuario" + +#: 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 "Progreso" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "Tempo de execución" + +#: cps/templates/tasks.html:20 +msgid "Actions" +msgstr "Accións" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Esta tarefa cancelarase. Non se gardará ningún progreso feito por esta tarefa." + +#: 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 é unha tarefa programada, volverá a lanzarse na próxima hora programada." + +#: cps/templates/user_edit.html:20 +msgid "Reset user Password" +msgstr "Restablecer contrasinal de usuario" + +#: cps/templates/user_edit.html:43 +msgid "Language of Books" +msgstr "Linguaxe de libros" + +#: cps/templates/user_edit.html:54 +msgid "OAuth Settings" +msgstr "Axustes OAuth" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "Ligar" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "Desligar" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "Token de sincronización de Kobo" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "Crear/Ver" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "Forzar sincronización completa de kobo" + +#: cps/templates/user_edit.html:88 +msgid "Add allowed/Denied Custom Column Values" +msgstr "Engadir columnas de valores propios de Permitidos/Denegados" + +#: cps/templates/user_edit.html:137 +msgid "Sync only books in selected shelves with Kobo" +msgstr "Sincronizar con Kobo soamente os libros dos andeis seleccionados" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +msgid "Delete User" +msgstr "Borrar usuario" + +#: cps/templates/user_edit.html:159 +msgid "Generate Kobo Auth URL" +msgstr "Xerar Auth URL de Kobo" + +#: cps/templates/user_table.html:80 cps/templates/user_table.html:103 +msgid "Select..." +msgstr "Selección..." + +#: cps/templates/user_table.html:131 +msgid "Edit User" +msgstr "Editar usuario" + +#: cps/templates/user_table.html:134 +msgid "Enter Username" +msgstr "Introduce o nome do usuario" + +#: cps/templates/user_table.html:135 +#, fuzzy +msgid "Enter Email" +msgstr "Comprobar correo electrónico" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "Enter eReader Email" +msgstr "Enviar ao enderezo de correo electrónico do Kindle" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "eReader Email" +msgstr "Comprobar o correo electrónico" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "Lingua" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "Linguas de libros visibles" + +#: 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 Denegadas" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "Etiquetas Denegadas" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "Editar valores permitidos para a columna" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "Valores permitidos da columna" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "Editar valores non permitidos para a columna" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "Valores non permitidos dea columna" + +#: cps/templates/user_table.html:144 +msgid "Change Password" +msgstr "Cambiar a contrasinal" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "Vista" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "Editar andeis públicos" + +#: cps/templates/user_table.html:152 +msgid "Sync selected Shelves with Kobo" +msgstr "sincronizar andeis seleccionados con Kobo" + +#: cps/templates/user_table.html:156 +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Mostrar selección lidos/non lidos" + diff --git a/cps/translations/hu/LC_MESSAGES/messages.mo b/cps/translations/hu/LC_MESSAGES/messages.mo index 2faa8dc4..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 4d4bd63b..e72070e4 100644 --- a/cps/translations/hu/LC_MESSAGES/messages.po +++ b/cps/translations/hu/LC_MESSAGES/messages.po @@ -7,601 +7,644 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statisztika" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Rendszergazda oldala" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Alapvető beállítások" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Felhasználói felület beállításai" -#: cps/admin.py:289 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:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: 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:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: 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:599 +#: 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:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "" - -#: cps/admin.py:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" +#: 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:1253 -msgid "DB is not Writeable" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" +#: 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 "" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: 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:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Az e-mail kiszolgáló beállításai frissítve." - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Funkciók beállítása" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Az összes mezőt ki kell tölteni!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "Az e-mail tartománya nem érvényes." - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Új felhasználó hozzáadása" - -#: cps/admin.py:1427 +#: cps/admin.py:1326 #, python-format -msgid "User '%(user)s' created" -msgstr "A következő felhasználó létrehozva: %(user)s" +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:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Már létezik felhasználó ehhez az e-mail címhez vagy felhasználói névhez." +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "" -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "A felhasználó törölve: %(nick)s" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Az e-mail kiszolgáló beállításai frissítve." -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr " A felhasználó szerkesztése: %(nick)s" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "A felhasználó frissítve: %(nick)s" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Ismeretlen hiba történt. Próbáld újra később!" - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "SMTP beállítások változtatása" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1633 -#, 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: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:1635 -msgid "Please configure your e-mail address first..." +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1637 -msgid "E-mail server settings updated" -msgstr "Az e-mail kiszolgáló beállításai frissítve." - -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr " A felhasználó szerkesztése: %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Frissítési csomag kérése" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Frissítési csomag letöltése" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Frissítési csomag kitömörítése" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Fájlok cserélése" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Adatbázis kapcsolatok lezárva" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Szerver leállítása" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Kapcsolódási hiba" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Általános hiba" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: 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:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Funkciók beállítása" + +#: 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:1903 +msgid "E-mail is not from valid domain" +msgstr "Az e-mail tartománya nem érvényes." + +#: 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:1926 +#, fuzzy +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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "A felhasználó törölve: %(nick)s" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +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:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "A felhasználó frissítve: %(nick)s" + +#: cps/converter.py:31 msgid "not installed" msgstr "nincs telepítve" -#: cps/converter.py:31 +#: cps/converter.py:32 msgid "Execution permissions missing" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:917 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:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 +#: 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:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: 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:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "A metaadatok sikeresen frissültek" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "Metaadatok szerkesztése" +#: 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:457 +#: cps/editbooks.py:337 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +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: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:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: 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:634 -msgid "User has no rights to upload additional file formats" -msgstr "" - -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: 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:643 cps/editbooks.py:1033 +#: 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:655 +#: cps/editbooks.py:753 #, 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:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Nem sikerült elmenteni a %(file)s fájlt." +msgid "File %(filename)s could not saved to temp dir" +msgstr "" -#: cps/editbooks.py:683 +#: cps/editbooks.py:773 #, 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." - -#: cps/editbooks.py:697 cps/editbooks.py:809 -msgid "User has no rights to upload cover" +msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:828 -msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:869 -msgid "Metadata successfully updated" -msgstr "A metaadatok sikeresen frissültek" - -#: cps/editbooks.py:887 -msgid "Error editing book: {}" +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:951 -msgid "Uploaded book probably exists in the library, consider to change before upload new: " +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:1041 -#, python-format -msgid "File %(filename)s could not saved to temp dir" -msgstr "" +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "Metaadatok szerkesztése" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:992 #, python-format -msgid "Failed to Move Cover File %(file)s: %(error)s" +msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1117 -#, python-format -msgid "File %(file)s uploaded" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1143 -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: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:1151 +#: cps/editbooks.py:1200 #, 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" +msgid "Failed to store file %(file)s." +msgstr "Nem sikerült elmenteni a %(file)s fájlt." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1224 #, 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" +msgid "File format %(ext)s added to %(book)s" +msgstr "A(z) %(ext)s fájlformátum hozzáadva a könyvhez: %(book)s." #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -616,186 +659,181 @@ msgstr "A visszahívási tartomány nem ellenőrzött, kövesd az alábbi lépé 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Küldés Kindle-re" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Teszt e-mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Kezdő lépések a Calibre-Web-bel" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 konvertálása %(format)s-ra és küldés Kindle-re" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "%(format)s küldése Kindle-re" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Küldés Kindle-re" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Várakozás" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Nem sikerült" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Elindítva" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Végrehajtva" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Felfedezés" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Ismeretlen állapot" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -804,9 +842,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1613 +#: 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 @@ -865,12 +903,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -886,497 +925,617 @@ 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Legutóbbi könyvek mutatása" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Kelendő könyvek mutatása" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Felfedezés" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Keresés" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Kiadva ezután: " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Kiadva ezelőtt: " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Értékelés <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Értékelés <= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Részletes keresés" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "A megadott polc érvénytelen!" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Elnézést, nem vagy jogosult hozzáadni a könyvet a következő polcra: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "A könyv már a következő polcon van: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "A könyv hozzá lett adva a következő polchoz: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "A könyvek már a következő polcon vannak: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "A könyvek hozzá lettek adva a következő polchoz: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Nem sikerült hozzáadni a könyveket a polchoz: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "A könyv el lett távolítva a polcról: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Polc készítése" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Sajnálom, nincs jogosultságot eltávolítani könyvet erről a polcról: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Polc szerkesztése" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "A metaadatok sikeresen frissültek" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "A következő polc átrendezése: %(name)s" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: 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:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "A következő polc megváltoztatva: %(title)s" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Hiba történt" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "A metaadatok sikeresen frissültek" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "A következő polc átrendezése: %(name)s" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Polc: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Feladatok" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Várakozás" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Nem sikerült" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Elindítva" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Végrehajtva" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Ismeretlen állapot" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Ismeretlen adat a frissítési információk olvasásakor" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Nem érhető el újabb frissítés. Már a legújabb verzió van telepítve." -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Egy új frissítés érhető el. Kattints a lenti gombra a legújabb verzió frissítésére" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Nem lehetett begyűjteni a frissítési információkat" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Új frissítés érhető el. Kattints az alábbi gombra a frissítéshez a következő verzióra: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Nincs információ a kiadásról." -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Felfedezés (könyvek találomra)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Kelendő könyvek (legtöbbet letöltöttek)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Kiadó: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Sorozat: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Címke: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Nyelv: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Részletes keresés" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Keresés" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Letöltések" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Feladatok" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Kiadva ezután: " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Kiadva ezelőtt: " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Értékelés <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Értékelés <= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: 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:1527 +#: cps/web.py:1240 #, 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" +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:1531 +#: 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 "Hiba történt a könyv küldésekor: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: 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:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Az e-könyv átalakítás nem sikerült: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "Metaadatok szerkesztése" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Feltöltés" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Felhasználók listája" @@ -1389,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Rendszergazda" @@ -1406,13 +1566,8 @@ msgstr "Rendszergazda" msgid "Password" msgstr "Jelszó" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Feltöltés" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1426,7 +1581,7 @@ msgstr "" msgid "Edit" msgstr "Szerkesztés" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1437,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 @@ -1467,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 @@ -1539,78 +1690,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Adminisztráció" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Újracsatlakozás a Calibre adatbázishoz" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "A Calibre adatbázis újraindítása" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "A Calibre adatbázis leállítása" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Frissítés" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Verzió" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Részletek" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Jelenlegi verzió" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Frissítés keresése" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Frissítés elkezdése" -#: cps/templates/admin.html:210 +#: 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:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: 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:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Frissítés folyamatban, ne töltsd újra az oldalt" @@ -1622,39 +1804,39 @@ msgstr "keresztül" msgid "In Library" msgstr "Könyvtárban" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "csökkentsd" @@ -1662,165 +1844,166 @@ msgstr "csökkentsd" msgid "More by" msgstr "Több eszerint:" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Könyv törlése" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Formátumok törlése:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Könyvformátum átalakítása:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Konvertálás erről:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "Válassz egy lehetőséget" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Konvertálás erre:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Könyv konvertálása" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Könyv címe" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Szerző" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Leírás" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Címkék" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Értékelés" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Borító URL (jpg, borító letöltve és elmentve az adatbázisban, a mező újra üres lesz utána)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Borító feltöltése helyi meghajtóról" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Kiadás éve" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Kiadó" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Feltöltés formátuma" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Könyv megnézése szerkesztés után" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Metaadatok beszerzése" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Kulcsszó" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Keresési kulcsszó " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Kattints a borítóra a metadatok betöltésére" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Betöltés..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Forrás" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Keresési hiba!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Nincs találat! Próbálj másik kulcsszót." @@ -1913,7 +2096,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1929,6 +2112,7 @@ msgid "Enter " msgstr "Regisztrálás" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Biztosan?" @@ -2033,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 @@ -2049,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 @@ -2239,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" @@ -2251,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" @@ -2342,79 +2571,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: 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:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Legyen olvasatlan" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Legyen olvasott" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Olvasva" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Ismertető:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2438,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:29 +#: 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" @@ -2467,186 +2700,194 @@ msgstr "Tartomány megadása" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Kezdőlap" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Navigáció átkapcsolása" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Felhasználói fiók" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Kilépés" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Feltöltés..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Hiba" -#: cps/templates/layout.html:63 +#: 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:76 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 "Beállítások" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Felhasználói fiók" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Kilépés" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Böngészés" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Névjegy" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Előző" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Könyv részletei" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Emlékezz rám" @@ -2655,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" @@ -2751,7 +2992,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr " " @@ -2764,127 +3005,161 @@ msgstr "Calibre-Web e-könyv katalógus" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Világos" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Sötét" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Vissza" + +#: 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:116 -msgid "Light" -msgstr "Világos" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Sötét" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Rendszergazda oldala" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2892,7 +3167,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -2910,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 @@ -2929,15 +3204,19 @@ 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/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Találatok a következőhöz:" @@ -2949,64 +3228,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Polc törlése" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3051,8 +3338,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Alkalmazás könyvtár" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3078,9 +3365,17 @@ 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 "" + +#: 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" @@ -3146,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Teszt e-mail" #: cps/templates/user_table.html:137 @@ -3220,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 c57e4071..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 e3096b31..40f5ad5a 100644 --- a/cps/translations/it/LC_MESSAGES/messages.po +++ b/cps/translations/it/LC_MESSAGES/messages.po @@ -2,598 +2,638 @@ # 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-04-18 20:01+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" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistiche" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Ricollegato con successo" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Tutto OK! Database riconnesso" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando sconosciuto" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: 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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Pagina di amministrazione" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configurazione di base" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configurazione dell'interfaccia utente" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Modifica gli utenti" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Utente non trovato" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" -msgstr "{} utente eliminato con successo" +msgstr "{} utenti eliminati con successo" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Richiesta non formulata correttamente" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "L'utente Guest (ospite) non può avere questo ruolo" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ruolo non valido" -#: cps/admin.py:470 +#: 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:480 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "Visualizzazione invalida" +msgstr "Visualizzazione non valida" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Nessuna lingua valida indicata" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Nessuna lingua valida per il libro" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parametro non trovato" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Colonna di lettura non valida" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Colonna con restrizioni non valida" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "La configurazione di Calibre-Web è stata aggiornata" -#: cps/admin.py:591 +#: 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:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Vuoi veramente eliminare questo dominio?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Vuoi veramente eliminare questo utente?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Vuoi veramente eliminare questo scaffale?" -#: cps/admin.py:599 +#: 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 dell'/degli utente/i selezionato/i?" +msgstr "Sei sicuro di voler modificare le impostazioni locali del/degli utente/i selezionato/i?" -#: cps/admin.py:601 +#: 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 dell'/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:603 +#: 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 dell'/degli utente/i selezionato/i?" +msgstr "Sei sicuro di voler modificare il ruolo evidenziato del/degli utente/i selezionato/i?" -#: cps/admin.py:605 -#, fuzzy +#: 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 impostazioni delle restrizioni di visualizzazione dell'/degli utente/i selezionato/i?" +msgstr "Sei sicuro di voler modificare le restrizioni selezionate del/degli utente/i selezionato/i?" -#: cps/admin.py:607 +#: 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 impostazioni delle restrizioni di visualizzazione dell'/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:610 +#: 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:612 +#: 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:614 -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:764 -msgid "Tag not found" -msgstr "Etichetta non trovata" +#: 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:776 -msgid "Invalid Action" -msgstr "Azione non valida" +#: 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 sincronizzato di Calibre-Web e forzare una sincronizzazione completa con il tuo lettore Kobo?" -#: cps/admin.py:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "" +msgstr "{} voci di sincronizzazione eliminate" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Etichetta non trovata" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Azione non valida" -#: cps/admin.py:1059 +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Per favore indica un account di servizio LDAP" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Errore nel database: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "Il DB non è scrivibile" - -#: cps/admin.py:1266 -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:1270 -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:1378 -msgid "Database Settings updated" -msgstr "Configurazione del Database aggiornata" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "Configurazione del Database" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Aggiungi un nuovo utente" -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Per favore compila tutti i campi!" +#: 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:1410 -msgid "E-mail is not from valid domain" -msgstr "L'e-mail non proviene da un dominio valido" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Tutto OK! Account Gmail verificato." -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Aggiungi un nuovo utente" - -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" -msgstr "L'utente '%(user)s' è stato creato" +msgid "Oops! Database Error: %(error)s." +msgstr "Errore nel database: %(error)s." -#: cps/admin.py:1433 -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: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 accodata con successo per essere spedita a %(email)s, per favore controlla le attività per il risultato" -#: cps/admin.py:1463 +#: cps/admin.py:1326 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "L'utente '%(nick)s' è stato eliminato" +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:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "Non posso eliminare l'utente Guest (ospite)" +#: 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:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Non rimarrebbe nessun utente amministratore, non posso eliminare l'utente" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Le impostazioni del server e-mail sono state aggiornate" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Modifica l'utente %(nick)s" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Modifica le impostazioni delle attività pianificate" -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "L'utente '%(nick)s' è stato aggiornato" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Ora di inizio non valida per l'attività specificata" -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Si è verificato un errore sconosciuto: per favore riprova." +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Durata non valida per l'attività specificata" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Modifica le impostazioni del server e-mail" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Impostazioni delle attività pianificate aggiornate" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "L'account Gmail è stato verificato con successo" +#: 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:1630 -#, 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" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "Il DB delle impostazioni non è scrivibile" -#: cps/admin.py:1633 +#: cps/admin.py:1424 cps/admin.py:2039 #, 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:1635 -msgid "Please configure your e-mail address first..." -msgstr "Per favore prima configura il tuo indirizzo e-mail..." - -#: cps/admin.py:1637 -msgid "E-mail server settings updated" -msgstr "Configurazione del server e-mail aggiornata" +msgid "Edit User %(nick)s" +msgstr "Modifica l'utente %(nick)s" -#: cps/admin.py:1679 +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" -msgstr "Visualizzatore del Logfile" +msgstr "Visualizzatore del file di log" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" -msgstr "Richiedo il pacchetto di aggiornamento" +msgstr "Richiesta del pacchetto di aggiornamento" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" -msgstr "Scarico il pacchetto di aggiornamento" +msgstr "Download del pacchetto di aggiornamento" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" -msgstr "Decomprimo il pacchetto di aggiornamento" +msgstr "Decompressione del pacchetto di aggiornamento" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" -msgstr "Sostituisco i file" +msgstr "Sostituzione dei file" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Le connessioni al database sono chiuse" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" -msgstr "Arresto il server" +msgstr "Arresto del server" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Errore di connessione" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Errore generale" -#: cps/admin.py:1773 +#: 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:1774 +#: 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:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Errore: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} utente importato con successo" -#: cps/converter.py:30 -msgid "not installed" -msgstr "non installato" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Mancano i permessi di esecuzione" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Il DB non è scrivibile" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "La colonna personale no.%(column)d non esiste nel database di Calibre" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Nessuna" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Il formato del libro è stato eliminato con successo" +#: 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/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Il libro é stato eliminato con successo" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Impostazioni database aggiornate" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Configurazione del database" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -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/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Per favore compila tutti i campi!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "modifica i metadati" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "L'e-mail non proviene da un dominio valido" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s non è un numero valido, proseguo" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Aggiungi un nuovo utente" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s non è una lingua valida" +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "L'utente '%(user)s' è stato creato" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" -msgstr "" +#: 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/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, 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" +msgid "User '%(nick)s' deleted" +msgstr "L'utente '%(nick)s' è stato eliminato" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Il file da caricare deve avere un'estensione" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Non posso eliminare l'utente Guest (ospite)" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Impossibile creare la cartella %(path)s (autorizzazione negata)." +#: 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/editbooks.py:660 +#: 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:2043 #, python-format -msgid "Failed to store file %(file)s." -msgstr "Il salvataggio del file %(file)s non è riuscito." +msgid "User '%(nick)s' updated" +msgstr "L'utente '%(nick)s' è stato aggiornato" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "non installato" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Mancano i permessi di esecuzione" -#: cps/editbooks.py:683 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Ho aggiunto il formato %(ext)s al libro %(book)s" +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: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 "Nessuna" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "L'utente non ha i permessi per caricare le copertine" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "I metadati sono stati aggiornati con successo" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "Errore durante la modifica del libro: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Il file %(file)s è stato caricato" + +#: 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: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: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:951 +#: 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 cambiare prima di sottoporlo nuovamente: " +msgstr "Probabilmente il libro caricato esiste già nella libreria, cambialo prima di caricarlo nuovamente:" -#: cps/editbooks.py:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: 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:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Il libro è stato eliminato con successo" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Mancano le autorizzazioni per eliminare i libri" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "modifica i metadati" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Il file %(file)s è stato caricato" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s non è un numero valido, lo salto" -#: cps/editbooks.py:1143 -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: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:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Libro accodato con successo per essere convertito in %(book_format)s" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Impossibile creare il percorso %(path)s (autorizzazione negata)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Si è verificato un errore durante la conversione del libro: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Il salvataggio del file %(file)s non è riuscito." + +#: 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" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -601,193 +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: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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" -msgstr "Invia a Kindle" +#: 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:115 cps/helper.py:223 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "Questo e-mail è stato spedito tramite 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:113 -msgid "Calibre-Web test e-mail" -msgstr "E-mail di test da Calibre-Web" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" +msgstr "E-mail di prova di Calibre-Web" -#: cps/helper.py:114 -msgid "Test e-mail" -msgstr "E-mail di test" +#: cps/helper.py:116 +msgid "Test Email" +msgstr "E-mail di prova" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Inizia con Calibre-Web" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" -msgstr "Converti %(orig)s in %(format)s e spedisci a Kindle" +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:172 cps/helper.py:176 cps/helper.py:180 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to Kindle" -msgstr "Invia %(format)s a Kindle" +msgid "Send %(format)s to eReader" +msgstr "Invia %(format)s all'eReader" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to Kindle" -msgstr "%(book)s inviato a Kindle" +msgid "%(book)s send to eReader" +msgstr "%(book)s inviato all'eReader" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "Impossibile impostare lo stato di lettura: {}" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 -#, 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "Errore nel rinominare il file nel percorso: {}" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Questo nome di utente è già utilizzato" -#: cps/helper.py:669 -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:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" -msgstr "" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Errore nello scaricare la copertina" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" -msgstr "Errore di formato della copertina" +msgstr "Errore nel formato della copertina" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" -msgstr "" +msgstr "Non sei autorizzato ad accedere a localhost o alla rete locale per caricare le copertine" -#: cps/helper.py:783 +#: 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:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" -msgstr "" +msgstr "Contenuto del file di copertina non valido" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Non ho trovato il file binario di UnRar" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "Errore nell'eseguire UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Attendi" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Non riuscito" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Avviato" +#: cps/helper.py:1077 +msgid "Cover" +msgstr "Copertina" -#: cps/helper.py:943 -msgid "Finished" -msgstr "Terminato" +#: 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/helper.py:945 -msgid "Unknown Status" -msgstr "Stato sconosciuto" - -#: cps/kobo_auth.py:128 -#, fuzzy +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configurazione di Kobo" @@ -796,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:1613 +#: 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 @@ -808,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 @@ -827,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." @@ -857,12 +887,13 @@ msgstr "Google, errore Oauth: per favore riprova più tardi." msgid "Google Oauth error: {}" msgstr "Google, errore Oauth: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Stelle" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -876,548 +907,644 @@ 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Libri" -#: cps/render_template.py:43 +#: 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:44 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:46 +#: 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:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Libri scaricati" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: 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:68 +#: cps/render_template.py:69 msgid "Discover" -msgstr "Per scoprire" +msgstr "Da scoprire" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Valutazioni" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Libri archiviati" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Elenco libri" -#: cps/render_template.py:102 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: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 "Cerca" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Pubblicato dopo il " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Pubblicato prima del " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Valutazione <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Valutazione >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Stato di lettura = %(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Ricerca avanzata" -#: cps/shelf.py:67 cps/shelf.py:121 +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Lo scaffale specificato non è valido" -#: cps/shelf.py:73 -#, fuzzy +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" -msgstr "Mi spiace, ma non sei autorizzato ad aggiungere libri allo scaffale: %(shelfname)s" +msgstr "Mi spiace, ma non sei autorizzato ad aggiungere libri a questo scaffale" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Il libro è gia presente nello scaffale: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Il libro è stato aggiunto allo scaffale: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" -msgstr "" +msgstr "Non sei autorizzato ad aggiungere libri allo scaffale" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "I libri sono già presenti nello scaffale: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "I libri sono stati aggiunti allo scaffale: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Non posso aggiungere libri allo scaffale: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Il libro è stato rimosso dallo scaffale: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" -msgstr "" +msgstr "Spiacente, ma non sei autorizzato a rimuovere libri da questo scaffale" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crea uno scaffale" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" -msgstr "Spiacente, non sei autorizzato a modificare questo scaffale" +msgstr "Spiacente, ma non sei autorizzato a modificare questo scaffale" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Modifica uno scaffale" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Errore nell'eliminare lo scaffale" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Lo scaffale è stato eliminato con successo" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Modifica l'ordine dello scaffale: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" -msgstr "" +msgstr "Spiacente, ma non sei autorizzato a creare scaffali pubblici" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Lo scaffale %(title)s è stato creato" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Lo scaffale %(title)s è stato modificato" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" -msgstr "C'era un errore" +msgstr "C'è stato un errore" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Il libro é stato eliminato con successo" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Modifica l'ordine dello scaffale: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Scaffale: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Attività" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Attendi" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Non riuscito" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Avviato" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Finito" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Terminato" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Annullato" + +#: 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:433 cps/updater.py:545 +#: 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:451 +#: 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:469 +#: 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:479 +#: 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:488 cps/updater.py:502 cps/updater.py:513 +#: 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:531 +#: 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:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Scopri (libri casuali)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" -msgstr "I libri più richiesti" +msgstr "Libri hot (i più scaricati)" -#: cps/web.py:501 +#: 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:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autore: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editore: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serie: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Valutazione: nessuna" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Valutazione: %(rating)s stelle" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato del file: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoria: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Lingua: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Ricerca avanzata" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Cerca" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" -msgstr "Downloads" +msgstr "Scaricati" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Elenco delle valutazioni" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Elenco dei formati" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Compito" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Pubblicato dopo il " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Pubblicato prima del " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Valutazione <= %(rating)s" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "Prima configura le impostazioni del server SMTP..." -#: cps/web.py:1317 +#: cps/web.py:1240 #, python-format -msgid "Rating >= %(rating)s" -msgstr "Valutazione >= %(rating)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:1319 +#: cps/web.py:1243 #, python-format -msgid "Read Status = %(status)s" -msgstr "Stato di lettura = %(status)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:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "Errore di ricerca nelle colonne personalizzate. Per favore riavvia Calibre-Web" - -#: cps/web.py:1527 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Libro accodato con successo per essere spedito a %(kindlemail)s" +#: 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:1531 -#, 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" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Attendi un minuto per registrare l'utente successivo" -#: cps/web.py:1533 -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/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:1550 -msgid "E-Mail server is not configured, please contact your administrator!" +#: 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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 -msgid "Register" -msgstr "Registra" - -#: cps/web.py:1585 -msgid "Your e-mail is not allowed to register" -msgstr "Il tuo e-mail non è autorizzato alla registrazione" +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "La tua e-mail non è consentita." -#: cps/web.py:1588 -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:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "Tutto OK! L'e-mail di conferma è stata inviata." -#: cps/web.py:1602 +#: 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:1621 +#: 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:1627 +#: 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:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "Nome utente o password errati" -#: cps/web.py:1638 +#: 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:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "Si è verificato un errore sconosciuto. Per favore riprova più tardi." -#: cps/web.py:1644 +#: 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:1651 +#: 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Non ho trovato il convertitore %(tool)s di libri di Calibre" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "Non ho trovato il formato %(format)s nel disco" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "La conversione del libro è terminata con un errore sconosciuto" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Si è verificato un errore con il convertitore Kepubify: %(error)s" -#: cps/tasks/convert.py:223 +#: 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:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Errore nel convertitore: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Si è verificato un errore con Calibre: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Convertire" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Riconessione al database di Calibre" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-mail" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "Backup dei metadati" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "Sono state generate %(count)s miniature delle copertine" + +#: 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:289 +msgid "Generated {0} series thumbnails" +msgstr "Sono state generate {0} miniature delle serie" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "Cancellazione della cache delle miniature delle copertine" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "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 Kindle E-mail Address" -msgstr "Invia all'indirizzo e-mail di Kindle" +msgid "Send to eReader Email" +msgstr "E-mail dell'eReader" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: 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:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Upload" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 msgid "Edit" msgstr "Modifica" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1428,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" @@ -1454,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 @@ -1495,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" @@ -1507,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" @@ -1529,78 +1652,109 @@ msgstr "Modifica la configurazione di base" msgid "Edit UI Configuration" msgstr "Modifica la configurazione dell'interfaccia utente" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Attività pianificate" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: 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 Duration" +msgstr "Durata massima" + +#: 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 "Genera miniature delle copertine delle serie" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" -msgstr "Scarica Debug Package" +msgstr "Scarica il pacchetto di debug" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" -msgstr "Visualizza Logfile" - -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Ricollega il database di Calibre" +msgstr "Visualizza log" -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Riavvia Calibre-Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Arresta Calibre-Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Aggiornamento" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Informazioni sulla versione" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versione" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Dettagli" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versione attuale" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Ricerca aggiornamenti" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Esegui l'aggiornamento" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Vuoi veramente riavviare Calibre-Web?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Vuoi veramente arrestare Calibre-Web?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Aggiornamento, non ricaricare la pagina." @@ -1612,206 +1766,207 @@ msgstr "via" msgid "In Library" msgstr "Nella libreria" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Ordina secondo la data dei libri, prima i più recenti" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Ordina secondo la data dei libri, prima i più vecchi" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Ordina i titoli in ordine alfabetico" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Ordina i titoli in ordine alfabetico inverso" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Ordina secondo la data di pubblicazione, prima i più recenti" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Ordina secondo la data di pubblicazione, prima i più vecchi" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "riduci" #: cps/templates/author.html:99 msgid "More by" -msgstr "Altro da" +msgstr "Altri di" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Elimina libro" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Elimina i formati:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Converti il libro nel formato:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Converti da:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: 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:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Converti in:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Converti libro" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Titolo del libro" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Autore" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Descrizione" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identificatori" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Tipo di identificatore" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Valore dell'identificatore" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Rimuovi" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Aggiungi un identificatore" -#: cps/templates/book_edit.html:86 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:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID della serie" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Valutazione" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Carica la copertina da URL (jpeg - l'immagine della copertina viene scaricata e salvata nel database)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Carica la copertina dal disco locale" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Data di pubblicazione" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Editore" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Carica formato" -#: cps/templates/book_edit.html:208 +#: 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:211 cps/templates/book_edit.html:229 +#: 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:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Salva" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Parola chiave" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 msgid "Search keyword" msgstr "Cerca parola chiave" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Fai clic sulla copertina per caricare i metadati nel modulo" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Caricamento in corso..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Fonte" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Errore nella ricerca!" -#: cps/templates/book_edit.html:287 +#: 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 @@ -1829,19 +1984,19 @@ msgstr "Rimuovi le selezioni" #: cps/templates/book_table.html:41 msgid "Exchange author and title" -msgstr "Scambia autore e titolo" +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 @@ -1850,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" @@ -1874,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" @@ -1890,33 +2045,33 @@ 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 -#, fuzzy msgid "Enter comments" -msgstr "Digita il nome di dominio" +msgstr "Inserisci un commento" #: cps/templates/book_table.html:73 msgid "Comments" -msgstr "" +msgstr "Commento" #: cps/templates/book_table.html:75 -msgid "Archiv Status" -msgstr "" +msgid "Archive Status" +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 msgid "Are you really sure?" msgstr "Sei veramente sicuro?" @@ -1938,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" @@ -1950,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" @@ -1958,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" @@ -1970,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" @@ -1990,23 +2145,23 @@ msgstr "Nightly" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "" +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" @@ -2021,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 "" +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" @@ -2037,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)" @@ -2058,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" @@ -2142,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)" @@ -2154,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 - identifica automaticamente" +msgstr "Trova automaticamente" #: cps/templates/config_edit.html:281 msgid "Custom Filter" @@ -2190,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 @@ -2200,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" @@ -2217,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" @@ -2227,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" @@ -2237,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" @@ -2249,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" @@ -2257,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" @@ -2277,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" @@ -2318,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:60 cps/templates/detail.html:69 +#: 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:77 cps/templates/detail.html:94 +#: 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:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Pubblicato" -#: cps/templates/detail.html:221 +#: 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:221 +#: 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:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Letto" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Ripristina dall'archivio" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Aggiungi all'archivio" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archiviato" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descrizione:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2424,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:29 +#: 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" @@ -2447,193 +2648,200 @@ 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:170 +#: 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 -#, fuzzy msgid "Kobo Token:" -msgstr "Token Kobo Sync" +msgstr "Token di Kobo:" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Elenco" + +#: 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:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" -msgstr "" +msgstr "Ordina in ordine ascendente in base al numero di download" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" -msgstr "" +msgstr "Ordina in ordine discendente in base al numero di download" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Ordina gli autori in ordine alfabetico" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Ordina gli autori in ordine alfabetico inverso" -#: cps/templates/index.html:82 +#: 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:83 +#: 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Home" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" -msgstr "Alterna navigazione" +msgstr "Attiva/disattiva navigazione" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Ricerca nella libreria" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Account" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Disconnettersi" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." -msgstr "Uploading..." +msgstr "Caricamento in corso..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Errore" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." -msgstr "Caricamento riuscito, sto elaborando, per favore aspetta..." +msgstr "Caricamento riuscito, elaborazione in corso, attendi per favore..." -#: cps/templates/layout.html:76 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 "Configurazione" - -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Account" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Logout" +msgstr "Impostazioni" -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Per favore non ricaricare la pagina" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Naviga" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informazioni su" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Precedente" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Dettagli del libro" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Griglia" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Ricordami" @@ -2642,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" @@ -2656,7 +2864,7 @@ msgstr "Calibre-Web log: " #: cps/templates/logviewer.html:8 msgid "Stream output, can't be displayed" -msgstr "Flusso attivo, non può essere visualizzato" +msgstr "Flusso in uscita, non può essere visualizzato" #: cps/templates/logviewer.html:12 msgid "Show Access Log: " @@ -2672,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" @@ -2688,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" @@ -2696,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" @@ -2738,9 +2946,9 @@ msgstr "Cartella principale" msgid "Select" msgstr "Seleziona" -#: cps/templates/modal_dialogs.html:134 +#: 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" @@ -2750,127 +2958,159 @@ msgstr "Catalogo Calibre-Web" msgid "epub Reader" msgstr "Lettore epub" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Chiaro" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Scuro" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Seppia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Nero" + +#: 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:116 -msgid "Light" -msgstr "Chiaro" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Visualizzazione" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Scuro" +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "Pagina singola" -#: cps/templates/readcbr.html:122 +#: 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 all'inizio" +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" @@ -2878,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" @@ -2895,102 +3135,114 @@ 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." +msgstr "Questo link di verifica scadrà tra 10 minuti." + +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Genera miniature delle copertine delle serie" -#: cps/templates/search.html:5 +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Nessun risultato trovato" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Termine di ricerca:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" 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:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Cancella questo scaffale" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Modifica le caratteristiche dello scaffale" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Disponi i libri manualmente" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Disabilita la modifica della disposizione" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Abilita la modifica della disposizione" @@ -3035,8 +3287,8 @@ msgid "System Statistics" msgstr "Statistiche del sistema" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Programma libreria" +msgid "Program" +msgstr "Programma" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3048,7 +3300,7 @@ msgstr "Utente" #: cps/templates/tasks.html:14 msgid "Task" -msgstr "Operazione" +msgstr "Attività" #: cps/templates/tasks.html:15 msgid "Status" @@ -3062,9 +3314,17 @@ 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" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Questa attività verrà annullata. Tutti i progressi compiuti da questa attività verranno salvati." + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "Se si tratta di un'attività pianificata, verrà eseguita nuovamente durante il prossimo orario pianificato." #: cps/templates/user_edit.html:20 msgid "Reset user Password" @@ -3072,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" @@ -3088,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" @@ -3096,11 +3356,11 @@ msgstr "Crea/Visualizza" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" -msgstr "" +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" @@ -3124,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 Kindle E-mail Address" -msgstr "Digita l'email di Kindle" +msgid "Enter eReader Email" +msgstr "Inserisci l'e-mail dell'eReader" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "E-mail di Kindle" +msgid "eReader Email" +msgstr "E-mail dell'eReader" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3144,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" @@ -3176,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" @@ -3192,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 2c3247e1..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 ddadb332..51634bdc 100644 --- a/cps/translations/ja/LC_MESSAGES/messages.po +++ b/cps/translations/ja/LC_MESSAGES/messages.po @@ -7,600 +7,641 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2018-02-07 02:20-0500\n" -"Last-Translator: white \n" +"Last-Translator: subdiox \n" "Language: ja\n" "Language-Team: ja \n" -"Plural-Forms: nplurals=1; plural=0\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "統計" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" -msgstr "サーバを再起動しました。ページを再読み込みしてください" - -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" -msgstr "サーバをシャットダウンしています。ページを閉じてください" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." +msgstr "サーバーを再起動しました。ページを再読み込みしてください" #: cps/admin.py:151 -msgid "Reconnect successful" +#, fuzzy +msgid "Performing Server shutdown, please close window." +msgstr "サーバーをシャットダウンしています。ページを閉じてください" + +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" -msgstr "" +msgstr "不明なコマンド" + +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "%(email)s へのテストメール送信がキューに追加されました。結果を見るにはタスクを確認してください" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理者ページ" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本設定" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI設定" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" -msgstr "" +msgstr "ユーザーを編集" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" -msgstr "" +msgstr "全て" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" -msgstr "" +msgstr "ユーザーが見つかりません" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" -msgstr "" +msgstr "{}人のユーザーが削除されました" -#: cps/admin.py:397 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 "" +msgstr "全て表示" -#: cps/admin.py:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" -msgstr "" +msgstr "不正なリクエスト" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" -msgstr "" +msgstr "ゲストユーザーの名前は変更できません" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" -msgstr "" +msgstr "ゲストユーザーはこのロールを持つことができません" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" -msgstr "" +msgstr "管理者ユーザーが残っておらず、管理者ロールを削除できません" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" -msgstr "" +msgstr "値はtrueかfalseのどちらかでなければなりません" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" -msgstr "" +msgstr "無効なロール" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" -msgstr "" +msgstr "ゲストユーザーはこの画面を表示できません" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "" +msgstr "無効な表示" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" -msgstr "" +msgstr "ゲストユーザーの言語設定は自動的に決定されるため、固定することはできません" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" -msgstr "" +msgstr "有効な言語設定がありません" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" -msgstr "" +msgstr "有効な本の言語がありません" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" -msgstr "" +msgstr "パラメータが見つかりません" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" -msgstr "" +msgstr "無効な読み取り列" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" -msgstr "" +msgstr "無効な制限列" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" -msgstr "Calibre-Web の設定を更新しました" +msgstr "Calibre-Webの設定を更新しました" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" -msgstr "" +msgstr "Koboのトークンを削除してもよろしいですか?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" -msgstr "" +msgstr "このドメインを削除してもよろしいですか?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" -msgstr "" +msgstr "このユーザーを削除してもよろしいですか?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" -msgstr "" +msgstr "この本棚を削除してもよろしいですか?" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" -msgstr "" +msgstr "選択したユーザーの言語設定を変更してもよろしいですか?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" -msgstr "" +msgstr "選択したユーザーが表示できる本の言語を変更してもよろしいですか?" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" -msgstr "" +msgstr "選択したユーザーの選択したロールを変更してもよろしいですか?" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" -msgstr "" +msgstr "選択したユーザーの選択した制限を変更してもよろしいですか?" -#: cps/admin.py:607 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" -msgstr "" +msgstr "選択したユーザーの選択した表示制限を変更してもよろしいですか?" -#: cps/admin.py:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" -msgstr "" +msgstr "選択したユーザーの本棚同期の動作を変更してもよろしいですか?" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" -msgstr "" +msgstr "Calibreライブラリのパスを変更してもよろしいですか?" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" -msgstr "" +#: 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:776 -msgid "Invalid Action" -msgstr "" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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 "" +msgstr "拒否" -#: cps/admin.py:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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 "" +msgstr "許可" -#: cps/admin.py:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "" +msgstr "{}件の同期項目を削除しました" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "タグが見つかりません" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "無効なアクションです" -#: cps/admin.py:1059 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" -msgstr "" +msgstr "client_secrets.jsonがWebアプリケーション用に設定されていません" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" -msgstr "" +msgstr "ログファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" -msgstr "" +msgstr "アクセスログファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" -msgstr "" +msgstr "LDAPのプロバイダ、ポート番号、DN、ユーザーIDを入力してください" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" -msgstr "" +msgstr "LDAPのサービスアカウント名とパスワードを入力してください" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" -msgstr "" +msgstr "LDAPのサービスアカウント名を入力してください" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" -msgstr "" +msgstr "LDAPのグループフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" -msgstr "" +msgstr "LDAPのグループフィルタ内の括弧が一致しません" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" -msgstr "" +msgstr "LDAPのユーザーフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" -msgstr "" +msgstr "LDAPのユーザーフィルタ内の括弧が一致しません" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" -msgstr "" +msgstr "LDAPのメンバーフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" -msgstr "" +msgstr "LDAPのメンバーフィルタ内の括弧が一致しません" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" +msgstr "LDAPのCA証明書、証明書、キーの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "新規ユーザーを追加" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "メールサーバー設定を編集" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "メールサーバの設定を更新しました" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "機能設定" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "全ての項目を入力してください" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "このメールは有効なドメインからのものではありません" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "新規ユーザ追加" - -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" -msgstr "ユーザ '%(user)s' を作成しました" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "このメールアドレスかニックネームで登録されたアカウントが見つかりました" +msgid "Oops! Database Error: %(error)s." +msgstr "DBエラー: %(error)s" -#: cps/admin.py:1463 +#: cps/admin.py:1323 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "ユーザ '%(nick)s' を削除しました" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "" - -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "" +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "%(email)s へのテストメール送信がキューに追加されました。結果を見るにはタスクを確認してください" -#: cps/admin.py:1542 cps/admin.py:1667 +#: cps/admin.py:1326 #, python-format -msgid "Edit User %(nick)s" -msgstr "%(nick)s を編集" +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "%(res)s へのテストメール送信中にエラーが発生しました" -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "ユーザ '%(nick)s' を更新しました" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "初めにメールアドレスを設定してください" -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "不明なエラーが発生しました。あとで再試行してください。" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "メールサーバーの設定を更新しました" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "SMTP設定を変更" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "スケジュールタスク設定を編集" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "指定したタスクの開始時刻が無効です" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" -msgstr "" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "指定したタスクの期間が無効です" -#: cps/admin.py:1633 -#, python-format -msgid "There was an error sending the Test e-mail: %(res)s" -msgstr "テストメールを %(res)s に送信中にエラーが発生しました" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "スケジュールタスクの設定を更新しました" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." -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:1637 -msgid "E-mail server settings updated" -msgstr "メールサーバの設定を更新しました" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "設定DBが書き込みできません" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" -msgstr "%(user)s 用のパスワードをリセット" +msgid "Edit User %(nick)s" +msgstr "ユーザー %(nick)s を編集" -#: cps/admin.py:1685 cps/web.py:1522 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "ユーザー %(user)s のパスワードをリセット" + +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "初めにSMTPメールの設定をしてください" -#: cps/admin.py:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" -msgstr "" +msgstr "ログファイルビューア" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "更新データを要求中" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "更新データをダウンロード中" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "更新データを展開中" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "ファイルを置換中" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" -msgstr "データベースの接続を切断完了" +msgstr "DB接続を切断" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" -msgstr "サーバ停止中" +msgstr "サーバー停止中" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" -msgstr "アップデート完了、OKを押してページをリロードしてください" +msgstr "アップデート完了、OKを押してページを再読み込みしてください" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTPエラー" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "接続エラー" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" -msgstr "接続を確立中にタイムアウトしました" +msgstr "接続確立中にタイムアウトしました" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "エラー発生" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" -msgstr "" +msgstr "更新データを一時フォルダに保存できませんでした" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" -msgstr "" +msgstr "更新中にファイルを置換できませんでした" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" -msgstr "" +msgstr "少なくとも1人のLDAPユーザーの抽出に失敗しました" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" -msgstr "" +msgstr "少なくとも1人のLDAPユーザーの作成に失敗しました" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" -msgstr "" +msgstr "エラー: %(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" -msgstr "" +msgstr "エラー: LDAPサーバーのレスポンスでユーザーが返されません" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" -msgstr "" +msgstr "DB内にLDAPユーザーが1人も見つかりません" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" -msgstr "" +msgstr "{}人のユーザーをインポートしました" -#: cps/converter.py:30 -msgid "not installed" -msgstr "インストールされていません" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "DBの場所が無効です。正しいパスを入力してください" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "DBへの書き込みができません" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "キーファイルの場所が無効です。正しいパスを入力してください" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "なし" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "証明書ファイルの場所が無効です。正しいパスを入力してください" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "DB設定を更新しました" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "DB設定" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "全ての項目を入力してください" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "メタデータを編集" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "このメールは有効なドメインからのものではありません" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "新規ユーザー追加" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "" +msgid "User '%(user)s' created" +msgstr "ユーザー '%(user)s' を作成しました" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s は有効な言語ではありません" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "このメールアドレスかニックネームで登録されたアカウントがすでに存在します。" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "ユーザー '%(nick)s' を削除しました" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "ゲストユーザーは削除できません" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "管理者ユーザーが残っておらず、ユーザーを削除できません" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "ファイル拡張子 '%(ext)s' をこのサーバにアップロードすることは許可されていません" +msgid "User '%(nick)s' updated" +msgstr "ユーザー '%(nick)s' を更新しました" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "アップロードするファイルには拡張子が必要です" +#: cps/converter.py:31 +msgid "not installed" +msgstr "インストールされていません" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "%(path)s の作成に失敗しました (Permission denied)。" +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "実行権限がありません" -#: cps/editbooks.py:660 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Failed to store file %(file)s." -msgstr "%(file)s を保存できません。" +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "カスタムカラムの%(column)d列目がcalibreのDBに存在しません" -#: cps/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "ファイル形式 %(ext)s が %(book)s に追加されました" +#: 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 "なし" + +#: 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:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "ユーザーは表紙をアップロードする権限がありません" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" -msgstr "" +msgstr "IDは大文字小文字を区別しません。元のIDを上書きします" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "メタデータを更新しました" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "本編集中のエラー: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "ファイル %(file)s をアップロードしました" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "変換元の形式または変換後の形式が指定されていません" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "本の %(book_format)s への変換がキューに追加されました" -#: cps/editbooks.py:951 +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "この本の変換中にエラーが発生しました: %(res)s" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " -msgstr "" +msgstr "アップロードした本はすでにライブラリに存在します。新しくアップロードする前に変更を加えてください: " + +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s' は有効な言語ではありません" -#: cps/editbooks.py:1041 +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "アップロードするファイルには拡張子が必要です" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" -msgstr "" +msgstr "ファイル %(filename)s は一時フォルダに保存できませんでした" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" -msgstr "" +msgstr "表紙ファイル %(file)s の移動に失敗しました: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "本の形式を削除しました" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "本を削除しました" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "本を削除する権限がありません" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "メタデータを編集" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s は有効な数字ではありません。スキップします" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "変換元の形式または変換後の形式が指定されていません" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "新たなファイル形式をアップロードする権限がありません" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "本の %(book_format)s への変換がキューに追加されました" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "%(path)s の作成に失敗しました (Permission denied)。" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "この本の変換中にエラーが発生しました: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "ファイル %(file)s を保存できません。" + +#: 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ドライブの設定が完了していません。Googleドライブを無効化してから再度有効にしてみてください" +msgstr "Googleドライブの設定が完了していません。Googleドライブを無効にしてから再度有効にしてみてください" #: cps/gdrive.py:95 msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" @@ -611,261 +652,258 @@ msgstr "コールバックドメインが認証されていません。Google De 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" -msgstr "Kindleに送信" +#: 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:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web テストメール" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "テストメール" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Webを始める" -#: cps/helper.py:136 -#, python-format -msgid "Registration e-mail for user: %(name)s" -msgstr "ユーザ: %(name)s 用の登録メール" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" +msgstr "ユーザー: %(name)s 用の登録メール" -#: cps/helper.py:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" -msgstr "%(orig)s を %(format)s に変換してからKindleに送信" +#: 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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" -msgstr "Kindleに %(format)s を送信" +#: 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:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" -msgstr "Kindleに送信" +msgid "%(book)s send to eReader" +msgstr "%(book)s をE-Readerに送信" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "要求されたファイルを読み込めませんでした。権限設定が正しいか確認してください。" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "読み込みステータスを設定できません: {}" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" -msgstr "" +msgstr "%(id)s の本フォルダの削除に失敗しました。そこにはサブフォルダがあります: %(path)s" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" -msgstr "" +msgstr "本 %(id)s の削除に失敗しました: %(message)s" -#: cps/helper.py:393 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" -msgstr "" +msgstr "本 %(id)s はDBのみから削除されます。DB内の本のパスが有効ではありません: %(path)s" -#: cps/helper.py:458 -#, fuzzy, python-format +#: 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 に変更できませんでした。" +msgstr "エラー: %(error)s により、著者名を %(src)s から %(dest)s に変更できませんでした" -#: cps/helper.py:529 cps/helper.py:538 +#: 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:572 +#: 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 に変更できませんでした。" +msgstr "エラー: %(error)s により、タイトルを %(src)s から %(dest)s に変更できませんでした" -#: cps/helper.py:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "ファイル名の変更でエラーが発生しました: {}" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "本のパス %(path)s はGoogleドライブ上にありません" -#: cps/helper.py:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" -msgstr "" +msgstr "このユーザー名はすでに使われています" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" -msgstr "" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "メールアドレスの形式が無効" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: 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 "" +msgstr "表紙のダウンロードに失敗しました" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" -msgstr "" +msgstr "表紙形式エラー" -#: cps/helper.py:773 +#: 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:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" -msgstr "" +msgstr "表紙ファイルの作成に失敗しました" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" -msgstr "" +msgstr "表紙ファイルが有効な画像ファイルでないか、または保存できませんでした" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" -msgstr "" +msgstr "表紙ファイルは jpg/jpeg/png/webp/bmp のみ対応しています" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" -msgstr "" +msgstr "表紙ファイルの内容が無効です" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" -msgstr "" +msgstr "表紙ファイルは jpg/jpeg のみ対応しています" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" -msgstr "" - -#: cps/helper.py:889 -msgid "Error excecuting UnRar" -msgstr "" +msgstr "Unrarのバイナリファイルが見つかりません" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "待機中" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "失敗" - -#: cps/helper.py:941 -msgid "Started" -msgstr "開始" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" +msgstr "Unrarの実行中にエラーが発生しました" -#: cps/helper.py:943 -msgid "Finished" -msgstr "終了" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "見つける" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "不明" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" -msgstr "" +msgstr "localhost以外からCalibre-Webにアクセスし、有効なKobo端末用APIエンドポイントを取得してください" -#: cps/kobo_auth.py:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" -msgstr "" +msgstr "Kobo設定" #: cps/oauth_bb.py:77 #, python-format msgid "Register with %(provider)s" -msgstr "" +msgstr "%(provider)s で登録" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1613 +#: 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 "" +msgstr "%(oauth)s との連携に成功しました" #: cps/oauth_bb.py:155 msgid "Login failed, No User Linked With OAuth Account" -msgstr "" +msgstr "ログイン失敗、OAuthアカウントと連携しているユーザーが存在しません" #: cps/oauth_bb.py:197 #, python-format msgid "Unlink to %(oauth)s Succeeded" -msgstr "" +msgstr "%(oauth)s との連携解除に成功しました" #: cps/oauth_bb.py:202 #, python-format msgid "Unlink to %(oauth)s Failed" -msgstr "" +msgstr "%(oauth)s との連携解除に失敗しました" #: cps/oauth_bb.py:205 #, python-format msgid "Not Linked to %(oauth)s" -msgstr "" +msgstr "%(oauth)s と連携していません" #: cps/oauth_bb.py:261 msgid "Failed to log in with GitHub." -msgstr "" +msgstr "GitHubアカウントでのログインに失敗しました。" #: cps/oauth_bb.py:267 msgid "Failed to fetch user info from GitHub." -msgstr "" +msgstr "GitHubからのユーザー情報取得に失敗しました。" #: cps/oauth_bb.py:279 msgid "Failed to log in with Google." -msgstr "" +msgstr "Googleアカウントでのログインに失敗しました。" #: cps/oauth_bb.py:285 msgid "Failed to fetch user info from Google." -msgstr "" +msgstr "Googleからのユーザー情報取得に失敗しました。" #: cps/oauth_bb.py:332 msgid "GitHub Oauth error, please retry later." -msgstr "" +msgstr "GitHub OAuth エラー、再度お試しください。" #: cps/oauth_bb.py:335 msgid "GitHub Oauth error: {}" -msgstr "" +msgstr "GitHub OAuth エラー: {}" #: cps/oauth_bb.py:356 msgid "Google Oauth error, please retry later." -msgstr "" +msgstr "Google OAuth エラー、再度お試しください。" #: cps/oauth_bb.py:359 msgid "Google Oauth error: {}" -msgstr "" +msgstr "Google OAuth エラー: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" -msgstr "" +msgstr "星{}" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "ログイン" @@ -881,517 +919,635 @@ msgstr "トークンが無効です" msgid "Success! Please return to your device" msgstr "成功です!端末に戻ってください" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" -msgstr "" +msgstr "本" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "最近追加された本を表示" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "人気の本" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" -msgstr "" +msgstr "人気の本を表示" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" -msgstr "" +msgstr "ダウンロードされた本" -#: cps/render_template.py:50 cps/render_template.py:55 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" -msgstr "" +msgstr "ダウンロードされた本を表示" -#: cps/render_template.py:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" -msgstr "" +msgstr "高評価の本" -#: cps/render_template.py:60 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" -msgstr "" +msgstr "高評価の本を表示" -#: cps/render_template.py:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" -msgstr "読んだ本" +msgstr "既読の本" -#: cps/render_template.py:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "既読の本と未読の本を表示" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" -msgstr "" +msgstr "未読の本を表示" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "見つける" -#: cps/render_template.py:70 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 "ランダムで本を表示" +msgstr "ランダムに本を表示" -#: cps/render_template.py:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" -msgstr "" +msgstr "評価" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" -msgstr "" +msgstr "ファイル形式" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" -msgstr "" +msgstr "アーカイブされた本" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" -msgstr "" +msgstr "本の一覧" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" -msgstr "" +msgstr "本の一覧を表示" + +#: 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 "検索" + +#: cps/search.py:188 +msgid "Published after " +msgstr "これ以降に出版 " + +#: cps/search.py:195 +msgid "Published before " +msgstr "これ以前に出版 " -#: cps/shelf.py:67 cps/shelf.py:121 +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "評価 <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "評価 >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "既読/未読状況 = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "カスタムカラムの検索でエラーが発生しました。Calibre-Webを再起動してください" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "詳細検索" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "指定された本棚は無効です" -#: cps/shelf.py:73 -#, fuzzy +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" -msgstr "申し訳ありませんが、あなたは %(shelfname)s に本を追加することが許可されていません" +msgstr "申し訳ありませんが、あなたはこの本棚に本を追加することが許可されていません" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "この本は %(shelfname)s にすでに追加されています" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "本を %(sname)s に追加しました" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" -msgstr "" +msgstr "あなたはこの本棚に本を追加することが許可されていません" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "これらの本は %(name)s にすでに追加されています" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "本が %(sname)s に追加されました" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "%(sname)s に本を追加できません" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "本が %(sname)s から削除されました" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" -msgstr "" +msgstr "申し訳ありませんが、あなたはこの本棚から本を削除することが許可されていません" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "本棚を作成する" -#: cps/shelf.py:236 -#, fuzzy +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" -msgstr "申し訳ありませんが、%(sname)s から本を削除することが許可されていません" +msgstr "申し訳ありませんが、あなたはこの本棚を編集することが許可されていません" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "本棚を編集する" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "本棚の削除中にエラーが発生しました" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "本棚を削除しました" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "'%(name)s' 内の本の順番を変更する" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" -msgstr "" +msgstr "申し訳ありませんが、あなたはみんなの本棚を作成することが許可されていません" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s を作成しました" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s を変更しました" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "エラーが発生しました" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." -msgstr "" +msgstr "'%(title)s' という名前のみんなの本棚はすでに存在します。" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." -msgstr "" - -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "メタデータを更新しました" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "'%(name)s' 内の本の順番を変更する" +msgstr "'%(title)s' という名前の本棚はすでに存在します。" -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "本棚: '%(name)s'" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "本棚を開けません。この本棚は存在しないかアクセスできません" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "タスク" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "待機中" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "失敗" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "開始" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "終了" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "終了" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "キャンセル" + +#: 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:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "アップデートはありません。すでに最新バージョンがインストールされています" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "アップデートが利用可能です。下のボタンをクリックして最新バージョンにアップデートしてください。" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "アップデート情報を取得できません" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." -msgstr "" +msgstr "下のボタンをクリックして最新の安定バージョンにアップデートしてください。" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "アップデートが利用可能です。下のボタンをクリックしてバージョン: %(version)s にアップデートしてください。" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "リリース情報がありません" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" -msgstr "本を見つける (ランダムで表示)" +msgstr "本を見つける (ランダムに表示)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" -msgstr "" +msgstr "人気の本 (最もダウンロードされた本)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" -msgstr "" +msgstr "%(user)s がダウンロードした本" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" -msgstr "" +msgstr "著者: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "シリーズ: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "評価: なし" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" -msgstr "" +msgstr "評価: 星%(rating)s" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" -msgstr "" +msgstr "ファイル形式: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "カテゴリ: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "言語: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "詳細検索" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "検索" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" -msgstr "" +msgstr "ダウンロード数" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" -msgstr "" +msgstr "評価一覧" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" -msgstr "" - -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "タスク" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "これ以降に出版 " +msgstr "ファイル形式一覧" -#: cps/web.py:1293 -msgid "Published before " -msgstr "これ以前に出版 " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "評価 <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "評価 >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "初めにSMTPメールの設定をしてください" -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "本の %(kindlemail)s への送信がキューに追加されました" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "本の %(eReadermail)s への送信がキューに追加されました" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" +msgstr "LDAP認証を有効化できません" + +#: cps/web.py:1360 +msgid "Please wait one minute before next login" msgstr "" -#: cps/web.py:1621 -#, python-format +#: 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 "" +msgstr "代わりに '%(nickname)s' としてログインします。LDAPサーバーにアクセスできないか、ユーザーが存在しません" -#: cps/web.py:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" -msgstr "" +msgstr "ログインできません: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" -msgstr "ユーザ名またはパスワードが違います" +msgstr "ユーザー名またはパスワードが違います" -#: cps/web.py:1638 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" -msgstr "" +msgstr "新しいパスワードがあなたのメールアドレスに送信されました" + +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "不明なエラーが発生しました。あとで再試行してください。" -#: cps/web.py:1644 +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" -msgstr "" +msgstr "パスワードをリセットするには、有効なユーザー名を入力してください" -#: cps/web.py:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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 "" +msgstr "OAuth情報を含んだ有効なgmail.jsonファイルが見つかりません" -#: cps/tasks/convert.py:154 +#: 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" -msgstr "" +msgstr "Calibre ebook-convert %(tool)s が見つかりません" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" -msgstr "" +msgstr "%(format)s 形式は存在しません" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" -msgstr "" +msgstr "Ebook converter が不明なエラーで失敗しました" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" -msgstr "" +msgstr "Kepubify-converter が失敗しました: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" -msgstr "" +msgstr "変換されたファイルが見つからないか、またはフォルダー %(folder)s 内に複数存在します" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Ebook-converter が失敗しました: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" -msgstr "" +msgstr "Calibre が失敗しました: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "変換" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Calibre DBと再接続中" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "メール" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "メタデータを編集" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "表紙サムネイルを%(count)s個生成しました" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "表紙サムネイル" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "シリーズのサムネイルを{0}個生成しました" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "アップロード" #: cps/templates/admin.html:9 msgid "Users" -msgstr "" +msgstr "ユーザー" #: 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 "ユーザ名" +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" -msgstr "" +msgid "Email" +msgstr "メールアドレス" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to Kindle E-mail Address" -msgstr "" +msgid "Send to eReader Email" +msgstr "E-Readerメールアドレス" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理者" @@ -1401,27 +1557,22 @@ msgstr "管理者" msgid "Password" msgstr "パスワード" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "アップロード" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "ダウンロード" #: cps/templates/admin.html:23 msgid "View Books" -msgstr "" +msgstr "閲覧" #: cps/templates/admin.html:24 cps/templates/user_table.html:131 #: cps/templates/user_table.html:148 msgid "Edit" msgstr "編集" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1430,27 +1581,23 @@ msgstr "削除" #: cps/templates/admin.html:26 msgid "Public Shelf" -msgstr "" - -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" +msgstr "みんなの本棚" #: cps/templates/admin.html:55 msgid "Import LDAP Users" -msgstr "" +msgstr "LDAPユーザーをインポート" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" -msgstr "" +msgid "Email Server Settings" +msgstr "メールサーバー設定" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 msgid "SMTP Hostname" -msgstr "" +msgstr "SMTPホスト名" #: cps/templates/admin.html:71 cps/templates/email_edit.html:35 msgid "SMTP Port" -msgstr "" +msgstr "SMTPポート番号" #: cps/templates/admin.html:75 cps/templates/email_edit.html:39 msgid "Encryption" @@ -1458,20 +1605,21 @@ msgstr "暗号化" #: cps/templates/admin.html:79 cps/templates/email_edit.html:47 msgid "SMTP Login" -msgstr "" +msgstr "SMTPログイン" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" -msgstr "" +msgid "From Email" +msgstr "Fromメールアドレス" #: cps/templates/admin.html:90 -msgid "E-Mail Service" -msgstr "" +#, fuzzy +msgid "Email Service" +msgstr "メールサービス" #: cps/templates/admin.html:91 msgid "Gmail via Oauth2" -msgstr "" +msgstr "OAuth2経由のGmail" #: cps/templates/admin.html:106 msgid "Configuration" @@ -1479,7 +1627,7 @@ msgstr "設定" #: cps/templates/admin.html:109 msgid "Calibre Database Directory" -msgstr "" +msgstr "Calibre DBのディレクトリ" #: cps/templates/admin.html:113 cps/templates/config_edit.html:68 msgid "Log Level" @@ -1491,123 +1639,153 @@ msgstr "ポート番号" #: cps/templates/admin.html:122 msgid "External Port" -msgstr "" +msgstr "外部ポート" #: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 msgid "Books per Page" -msgstr "" +msgstr "1ページに表示する冊数" #: cps/templates/admin.html:133 msgid "Uploads" -msgstr "" +msgstr "アップロード" #: cps/templates/admin.html:137 msgid "Anonymous Browsing" -msgstr "" +msgstr "匿名での閲覧" #: cps/templates/admin.html:141 msgid "Public Registration" -msgstr "" +msgstr "誰でも登録可能" #: cps/templates/admin.html:145 msgid "Magic Link Remote Login" -msgstr "" +msgstr "マジックリンクによるリモートログイン" #: cps/templates/admin.html:149 msgid "Reverse Proxy Login" -msgstr "" +msgstr "リバースプロキシによるログイン" #: cps/templates/admin.html:154 cps/templates/config_edit.html:173 msgid "Reverse Proxy Header Name" -msgstr "" +msgstr "リバースプロキシのヘッダー名" #: cps/templates/admin.html:159 -#, fuzzy msgid "Edit Calibre Database Configuration" -msgstr "Calibre-Web の設定を更新しました" +msgstr "Calibre DBの設定を編集" #: cps/templates/admin.html:160 msgid "Edit Basic Configuration" -msgstr "" +msgstr "基本設定を編集" #: cps/templates/admin.html:161 msgid "Edit UI Configuration" +msgstr "UI設定を編集" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "スケジュールタスク" + +#: 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 +msgid "Maximum Duration" +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 "シリーズの表紙サムネイルを生成" + +#: 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:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "表紙サムネイルのキャッシュを更新" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "管理" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" -msgstr "" +msgstr "デバッグパッケージをダウンロード" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" -msgstr "" +msgstr "ログを表示" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" -msgstr "" +msgstr "再起動" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" -msgstr "" +msgstr "シャットダウン" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "アップデート" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "バージョン情報" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "バージョン" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "詳細" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "現在のバージョン" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" -msgstr "" +msgstr "アップデートを確認" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" -msgstr "更新を実行" +msgstr "アップデートを実行" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" -msgstr "" +msgstr "再起動してもよろしいですか?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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 "" +msgstr "OK" -#: cps/templates/admin.html:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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 "" +msgstr "キャンセル" -#: cps/templates/admin.html:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" -msgstr "" +msgstr "シャットダウンしてもよろしいですか?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" -msgstr "" +msgstr "アップデート中です。このページをリロードしないでください" #: cps/templates/author.html:15 msgid "via" @@ -1617,205 +1795,205 @@ msgstr "経由" msgid "In Library" msgstr "ライブラリ内" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" +msgstr "追加日が新しい順にソート" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" +msgstr "追加日が古い順にソート" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" +msgstr "五十音順にソート" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" +msgstr "逆五十音順にソート" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" +msgstr "発売日が新しい順にソート" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" +msgstr "発売日が古い順にソート" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "減らす" #: cps/templates/author.html:99 msgid "More by" -msgstr "" +msgstr "同じ著者が書いた本: " -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "本を削除" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "削除する形式:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "変換する形式:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "変換元:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" -msgstr "選択肢を選ぶ" +msgstr "選択肢から選ぶ" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "変換先:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "本を変換" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "本のタイトル" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "著者" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "詳細" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" -msgstr "" +msgstr "識別子" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" -msgstr "" +msgstr "識別子タイプ" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" -msgstr "" +msgstr "識別子の値" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" -msgstr "" +msgstr "削除" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" -msgstr "" +msgstr "識別子を追加" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "タグ" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" -msgstr "" +msgstr "巻数" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "評価" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" -msgstr "" +msgstr "表紙をURLから取得 (JPEG画像がダウンロードされDBに保存されます)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" -msgstr "" +msgstr "表紙をアップロード" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" -msgstr "" +msgstr "発売日" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "出版社" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 -msgid "Yes" -msgstr "はい" - #: 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:47 +#: cps/templates/search_form.html:166 msgid "No" -msgstr "いいえ" +msgstr "未読" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" -msgstr "" +msgstr "アップロード形式" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" -msgstr "" +msgstr "保存後に本を表示" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" -msgstr "" +msgstr "メタデータを取得" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" +msgstr "保存" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "キーワード" -#: cps/templates/book_edit.html:233 -#, fuzzy +#: cps/templates/book_edit.html:234 msgid "Search keyword" -msgstr "キーワードを検索" +msgstr "キーワード検索" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "カバー画像をクリックしてメタデータをフォームに読み込んでください" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "読み込み中..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "閉じる" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "ソース" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "検索エラー" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "検索結果が見つかりません。別のキーワードで検索してみてください。" @@ -1823,31 +2001,31 @@ msgstr "検索結果が見つかりません。別のキーワードで検索し #: cps/templates/user_table.html:14 cps/templates/user_table.html:77 #: cps/templates/user_table.html:100 msgid "This Field is Required" -msgstr "" +msgstr "この項目は必須です" #: cps/templates/book_table.html:37 msgid "Merge selected books" -msgstr "" +msgstr "選択した本を統合" #: cps/templates/book_table.html:38 cps/templates/user_table.html:124 msgid "Remove Selections" -msgstr "" +msgstr "選択した本を削除" #: cps/templates/book_table.html:41 msgid "Exchange author and title" -msgstr "" +msgstr "著者とタイトルを交換" #: cps/templates/book_table.html:47 msgid "Update Title Sort automatically" -msgstr "" +msgstr "タイトルのよみがなを自動で更新" #: cps/templates/book_table.html:51 msgid "Update Author Sort automatically" -msgstr "" +msgstr "著者のよみがなを自動で更新" #: cps/templates/book_table.html:63 cps/templates/book_table.html:69 msgid "Enter Title" -msgstr "" +msgstr "タイトルを入力" #: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 #: cps/templates/shelf_edit.html:8 @@ -1856,92 +2034,91 @@ msgstr "タイトル" #: cps/templates/book_table.html:64 msgid "Enter Title Sort" -msgstr "" +msgstr "タイトルのよみがなを入力" #: cps/templates/book_table.html:64 msgid "Title Sort" -msgstr "" +msgstr "タイトルのよみがな" #: cps/templates/book_table.html:65 msgid "Enter Author Sort" -msgstr "" +msgstr "著者名のよみがなを入力" #: cps/templates/book_table.html:65 msgid "Author Sort" -msgstr "" +msgstr "著者名のよみがな" #: cps/templates/book_table.html:66 msgid "Enter Authors" -msgstr "" +msgstr "著者名を入力" #: cps/templates/book_table.html:67 msgid "Enter Categories" -msgstr "" +msgstr "カテゴリ名を入力" #: cps/templates/book_table.html:68 msgid "Enter Series" -msgstr "" +msgstr "シリーズ名を入力" #: cps/templates/book_table.html:69 msgid "Series Index" -msgstr "" +msgstr "巻数" #: cps/templates/book_table.html:70 msgid "Enter Languages" -msgstr "" +msgstr "言語を入力" #: cps/templates/book_table.html:71 msgid "Publishing Date" -msgstr "" +msgstr "発売日" #: cps/templates/book_table.html:72 msgid "Enter Publishers" -msgstr "" +msgstr "出版社を入力" #: cps/templates/book_table.html:73 -#, fuzzy msgid "Enter comments" -msgstr "ドメイン名を入力" +msgstr "コメントを入力" #: cps/templates/book_table.html:73 msgid "Comments" -msgstr "" +msgstr "コメント" #: cps/templates/book_table.html:75 -msgid "Archiv Status" -msgstr "" +msgid "Archive Status" +msgstr "アーカイブ状況" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" -msgstr "" +msgstr "既読/未読" #: 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 -#, fuzzy msgid "Enter " -msgstr "登録" +msgstr "入力: " #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "よろしいですか?" #: cps/templates/book_table.html:117 msgid "Books with Title will be merged from:" -msgstr "" +msgstr "このタイトルの本から" #: cps/templates/book_table.html:121 msgid "Into Book with Title:" -msgstr "" +msgstr "このタイトルの本に統合します" #: cps/templates/book_table.html:126 msgid "Merge" -msgstr "" +msgstr "統合" #: cps/templates/config_db.html:12 msgid "Location of Calibre Database" -msgstr "" +msgstr "Calibre DBの場所" #: cps/templates/config_db.html:22 msgid "Use Google Drive?" @@ -1957,7 +2134,7 @@ msgstr "Googleドライブ上のCalibreフォルダ" #: cps/templates/config_db.html:40 msgid "Metadata Watch Channel ID" -msgstr "" +msgstr "メタデータ監視用チャンネルID" #: cps/templates/config_db.html:43 msgid "Revoke" @@ -1965,27 +2142,27 @@ msgstr "取り消す" #: cps/templates/config_db.html:68 msgid "New db location is invalid, please enter valid path" -msgstr "" +msgstr "入力したDBの場所が無効です。有効なパスを入力してください" #: cps/templates/config_edit.html:18 msgid "Server Configuration" -msgstr "サーバ設定" +msgstr "サーバー設定" #: cps/templates/config_edit.html:25 msgid "Server Port" -msgstr "ポート" +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" -msgstr "" +msgstr "アップデートチャンネル" #: cps/templates/config_edit.html:45 msgid "Stable" @@ -1997,11 +2174,11 @@ msgstr "最新" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "" +msgstr "信頼するホスト名 (カンマ区切り)" #: cps/templates/config_edit.html:61 msgid "Logfile Configuration" -msgstr "ログファイルの設定" +msgstr "ログファイル設定" #: cps/templates/config_edit.html:77 msgid "Location and name of logfile (calibre-web.log for no entry)" @@ -2009,11 +2186,11 @@ msgstr "ログファイル名 (空欄の場合はcalibre-web.log)" #: cps/templates/config_edit.html:82 msgid "Enable Access Log" -msgstr "" +msgstr "アクセスログを保存する" #: cps/templates/config_edit.html:85 msgid "Location and name of access logfile (access.log for no entry)" -msgstr "" +msgstr "アクセスログのファイル名 (空欄の場合はaccess.log)" #: cps/templates/config_edit.html:96 msgid "Feature Configuration" @@ -2021,55 +2198,55 @@ msgstr "機能設定" #: cps/templates/config_edit.html:104 msgid "Convert non-English characters in title and author while saving to disk" -msgstr "" +msgstr "ダウンロード時にタイトルと著者名の中にある2バイト文字を変換する" #: cps/templates/config_edit.html:108 msgid "Enable Uploads" -msgstr "" +msgstr "アップロード機能を有効にする" #: 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 "(ユーザーにアップロード権限を与えることも忘れないでください)" #: cps/templates/config_edit.html:112 msgid "Allowed Upload Fileformats" -msgstr "" +msgstr "アップロードを許可するファイル形式" #: cps/templates/config_edit.html:118 msgid "Enable Anonymous Browsing" -msgstr "" +msgstr "匿名での閲覧を許可" #: cps/templates/config_edit.html:122 msgid "Enable Public Registration" -msgstr "" +msgstr "誰でも登録可能にする" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" -msgstr "" +msgid "Use Email as Username" +msgstr "メールアドレスをユーザー名として使う" #: cps/templates/config_edit.html:132 msgid "Enable Magic Link Remote Login" -msgstr "" +msgstr "マジックリンクによるリモートログインを有効にする" #: cps/templates/config_edit.html:137 msgid "Enable Kobo sync" -msgstr "" +msgstr "Koboの同期を有効にする" #: cps/templates/config_edit.html:142 msgid "Proxy unknown requests to Kobo Store" -msgstr "" +msgstr "Koboストアへの不明なリクエストをプロキシ" #: cps/templates/config_edit.html:145 msgid "Server External Port (for port forwarded API calls)" -msgstr "" +msgstr "サーバーの外部ポート番号 (APIの呼び出しをポートフォワーディングするため)" #: cps/templates/config_edit.html:153 msgid "Use Goodreads" -msgstr "" +msgstr "Goodreadsを利用" #: cps/templates/config_edit.html:154 msgid "Create an API Key" -msgstr "" +msgstr "APIキーを作成" #: cps/templates/config_edit.html:158 msgid "Goodreads API Key" @@ -2081,158 +2258,204 @@ msgstr "GoodreadsのAPIシークレット" #: cps/templates/config_edit.html:169 msgid "Allow Reverse Proxy Authentication" -msgstr "" +msgstr "リバースプロキシの認証を許可" #: cps/templates/config_edit.html:180 msgid "Login type" -msgstr "" +msgstr "ログインの種類" #: cps/templates/config_edit.html:182 msgid "Use Standard Authentication" -msgstr "" +msgstr "通常の認証を利用" #: cps/templates/config_edit.html:184 msgid "Use LDAP Authentication" -msgstr "" +msgstr "LDAP認証を利用" #: cps/templates/config_edit.html:187 msgid "Use OAuth" -msgstr "" +msgstr "OAuthを利用" #: cps/templates/config_edit.html:194 msgid "LDAP Server Host Name or IP Address" -msgstr "" +msgstr "LDAPサーバーのホスト名またはIPアドレス" #: cps/templates/config_edit.html:198 msgid "LDAP Server Port" -msgstr "" +msgstr "LDAPサーバーのポート番号" #: cps/templates/config_edit.html:202 msgid "LDAP Encryption" -msgstr "" +msgstr "LDAPの暗号化方式" #: cps/templates/config_edit.html:205 msgid "TLS" -msgstr "" +msgstr "TLS" #: cps/templates/config_edit.html:206 msgid "SSL" -msgstr "" +msgstr "SSL" #: cps/templates/config_edit.html:210 msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" -msgstr "" +msgstr "LDAPのCA証明書のパス (クライアント証明書による認証の場合のみ必要)" #: cps/templates/config_edit.html:217 msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" -msgstr "" +msgstr "LDAP証明書のパス (クライアント証明書による認証の場合のみ必要)" #: cps/templates/config_edit.html:224 msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" -msgstr "" +msgstr "LDAPのキーファイルのパス (クライアント証明書による認証の場合のみ必要)" #: cps/templates/config_edit.html:233 msgid "LDAP Authentication" -msgstr "" +msgstr "LDAP認証" #: cps/templates/config_edit.html:235 msgid "Anonymous" -msgstr "" +msgstr "匿名" #: cps/templates/config_edit.html:236 msgid "Unauthenticated" -msgstr "" +msgstr "認証失敗" #: cps/templates/config_edit.html:237 msgid "Simple" -msgstr "" +msgstr "簡単" #: cps/templates/config_edit.html:242 msgid "LDAP Administrator Username" -msgstr "" +msgstr "LDAP管理者のユーザー名" #: cps/templates/config_edit.html:248 msgid "LDAP Administrator Password" -msgstr "" +msgstr "LDAP管理者のパスワード" #: cps/templates/config_edit.html:253 msgid "LDAP Distinguished Name (DN)" -msgstr "" +msgstr "LDAPの識別名 (DN)" #: cps/templates/config_edit.html:257 msgid "LDAP User Object Filter" -msgstr "" +msgstr "LDAPユーザーフィルタ" #: cps/templates/config_edit.html:262 msgid "LDAP Server is OpenLDAP?" -msgstr "" +msgstr "LDAPサーバーはOpenLDAPですか?" #: cps/templates/config_edit.html:264 msgid "Following Settings are Needed For User Import" -msgstr "" +msgstr "以下の設定はユーザーのインポートのために必要です" #: cps/templates/config_edit.html:266 msgid "LDAP Group Object Filter" -msgstr "" +msgstr "LDAPグループフィルタ" #: cps/templates/config_edit.html:270 msgid "LDAP Group Name" -msgstr "" +msgstr "LDAPグループ名" #: cps/templates/config_edit.html:274 msgid "LDAP Group Members Field" -msgstr "" +msgstr "LDAPグループメンバーフィールド" #: cps/templates/config_edit.html:278 msgid "LDAP Member User Filter Detection" -msgstr "" +msgstr "LDAPメンバーユーザーフィルタ検出" #: cps/templates/config_edit.html:280 msgid "Autodetect" -msgstr "" +msgstr "自動検出" #: cps/templates/config_edit.html:281 msgid "Custom Filter" -msgstr "" +msgstr "カスタムフィルタ" #: cps/templates/config_edit.html:286 msgid "LDAP Member User Filter" -msgstr "" +msgstr "LDAPメンバーユーザーフィルタ" #: cps/templates/config_edit.html:297 #, python-format msgid "Obtain %(provider)s OAuth Credential" -msgstr "" +msgstr "%(provider)s OAuth 認証情報を入手" #: cps/templates/config_edit.html:300 #, python-format msgid "%(provider)s OAuth Client Id" +msgstr "%(provider)s OAuth クライアントID" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "%(provider)s OAuth クライアントシークレット" + +#: cps/templates/config_edit.html:320 +msgid "External binaries" +msgstr "外部バイナリ" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "Calibre E-Book Converterのパス" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "Calibre E-Book Converterの設定" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "Kepubify E-Book Converterのパス" + +#: cps/templates/config_edit.html:345 +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:304 -#, python-format -msgid "%(provider)s OAuth Client Secret" +#: cps/templates/config_edit.html:375 +msgid "Strong" msgstr "" -#: cps/templates/config_edit.html:320 -msgid "External binaries" -msgstr "外部バイナリ" +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "パスワードをリセット" -#: cps/templates/config_edit.html:326 -msgid "Path to Calibre E-Book Converter" +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" msgstr "" -#: cps/templates/config_edit.html:334 -msgid "Calibre E-Book Converter Settings" +#: cps/templates/config_edit.html:389 +msgid "Enforce number" msgstr "" -#: cps/templates/config_edit.html:337 -msgid "Path to Kepubify E-Book Converter" +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" msgstr "" -#: cps/templates/config_edit.html:345 -msgid "Location of Unrar binary" -msgstr "Unrarバイナリのパス" +#: 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" @@ -2240,13 +2463,13 @@ msgstr "表示設定" #: cps/templates/config_view_edit.html:32 msgid "No. of Random Books to Display" -msgstr "" +msgstr "ランダムに表示する本の冊数" #: cps/templates/config_view_edit.html:36 msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" -msgstr "" +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 "テーマ" @@ -2260,27 +2483,27 @@ msgstr "caliBlur! ダークテーマ" #: cps/templates/config_view_edit.html:47 msgid "Regular Expression for Ignoring Columns" -msgstr "" +msgstr "無視するカラムの正規表現" #: cps/templates/config_view_edit.html:51 msgid "Link Read/Unread Status to Calibre Column" -msgstr "" +msgstr "既読/未読をリンクするCalibreのカラム" #: cps/templates/config_view_edit.html:60 msgid "View Restrictions based on Calibre column" -msgstr "" +msgstr "表示制限をリンクするCalibreのカラム" #: cps/templates/config_view_edit.html:69 msgid "Regular Expression for Title Sorting" -msgstr "" +msgstr "タイトルをソートするための正規表現" #: cps/templates/config_view_edit.html:80 msgid "Default Settings for New Users" -msgstr "" +msgstr "新規ユーザーのデフォルト設定" #: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 msgid "Admin User" -msgstr "" +msgstr "管理者ユーザー" #: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 msgid "Allow Downloads" @@ -2288,7 +2511,7 @@ msgstr "ダウンロードを許可" #: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 msgid "Allow eBook Viewer" -msgstr "" +msgstr "本のビューアを許可" #: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 msgid "Allow Uploads" @@ -2300,7 +2523,7 @@ msgstr "編集を許可" #: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 msgid "Allow Delete Books" -msgstr "" +msgstr "本の削除を許可" #: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 msgid "Allow Changing Password" @@ -2311,109 +2534,112 @@ msgid "Allow Editing Public Shelves" msgstr "みんなの本棚の編集を許可" #: cps/templates/config_view_edit.html:123 -#, fuzzy msgid "Default Language" -msgstr "言語を除外" +msgstr "言語設定のデフォルト" #: cps/templates/config_view_edit.html:131 msgid "Default Visible Language of Books" -msgstr "" +msgstr "表示する本の言語設定のデフォルト" #: cps/templates/config_view_edit.html:147 msgid "Default Visibilities for New Users" -msgstr "" +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 "" +msgstr "詳細画面でランダムに本を表示" #: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 msgid "Add Allowed/Denied Tags" -msgstr "" +msgstr "許可/拒否タグを追加" #: cps/templates/config_view_edit.html:167 msgid "Add Allowed/Denied custom column values" -msgstr "" +msgstr "許可/拒否カスタムカラムを追加" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" -msgstr "" +msgstr "ブラウザで読む" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" -msgstr "" +msgstr "ブラウザで聞く" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" -msgstr "" +msgstr "%(range)s 第%(index)s巻" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" -msgstr "" +msgstr "発売日" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "未読に設定" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "既読に設定" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" -msgstr "読んだ" +msgstr "既読" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" -msgstr "" +msgstr "アーカイブから復元" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" -msgstr "" +msgstr "アーカイブに追加" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" -msgstr "" +msgstr "アーカイブ済み" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "詳細:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "本棚に追加" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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 "" +msgstr "(公開)" -#: cps/templates/detail.html:298 +#: cps/templates/detail.html:339 msgid "Edit Metadata" -msgstr "" +msgstr "メタデータを編集" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" -msgstr "" +msgid "Email Account Type" +msgstr "サーバーの種類を選択" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" -msgstr "" +#, fuzzy +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 msgid "Revoke Gmail Access" -msgstr "" +msgstr "Gmailへのアクセスを失効" #: cps/templates/email_edit.html:42 msgid "STARTTLS" @@ -2425,24 +2651,25 @@ msgstr "SSL/TLS" #: cps/templates/email_edit.html:51 msgid "SMTP Password" -msgstr "" +msgstr "SMTPのパスワード" #: cps/templates/email_edit.html:58 msgid "Attachment Size Limit" -msgstr "" +msgstr "添付ファイルのサイズ制限" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" -msgstr "" +#, fuzzy +msgid "Save and Send Test Email" +msgstr "保存してテストメールを送信" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:29 +#: 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 "" +msgstr "許可するドメイン名 (ホワイトリスト)" #: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 msgid "Add Domain" @@ -2459,594 +2686,644 @@ msgstr "ドメイン名を入力" #: cps/templates/email_edit.html:92 msgid "Denied Domains (Blacklist)" -msgstr "" +msgstr "拒否するドメイン名 (ブラックリスト)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 "" +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:" -msgstr "" +msgstr "Koboトークン:" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "一覧" + +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" -msgstr "" +msgstr "Calibre-Webインスタンスが未設定です。管理者に連絡してください" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" -msgstr "" +msgstr "Issueを作成" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" -msgstr "" +msgstr "ホームに戻る" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" -msgstr "" +msgstr "ユーザーをログアウト" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" -msgstr "" +msgstr "ダウンロード数が少ない順にソート" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" -msgstr "" - -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 -msgid "Sort authors in alphabetical order" -msgstr "" +msgstr "ダウンロード数が多い順にソート" #: cps/templates/index.html:78 cps/templates/search.html:35 #: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "著者名を五十音順にソート" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" -msgstr "" +msgstr "著者名を逆五十音順にソート" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" -msgstr "" +msgstr "巻数が小さい順にソート" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 msgid "Sort descending according to series index" -msgstr "" +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 "" +msgstr "五十音順の本" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" -msgstr "" +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 "" +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 "" +msgstr "言語順" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" -msgstr "" +msgstr "評価順" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" -msgstr "" +msgstr "ファイル形式順" -#: cps/templates/index.xml:119 cps/templates/layout.html:135 -#: 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 "" +msgstr "本棚" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" -msgstr "" +msgstr "本棚に整理された本" -#: cps/templates/layout.html:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "ホーム" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" -msgstr "" +msgstr "ナビゲーションを実行" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" -msgstr "" +msgstr "ライブラリ内を検索" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "アカウント" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "ログアウト" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "アップロード中..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "エラー" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "アップロード完了。現在処理中ですのでお待ち下さい..." -#: cps/templates/layout.html:76 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 "設定" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "アカウント" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "ログアウト" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" -msgstr "" +msgstr "ページを更新しないでください" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "閲覧" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "このサイトについて" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "前" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "本の詳細" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "表" + #: cps/templates/login.html:18 msgid "Remember Me" -msgstr "" +msgstr "アカウント情報を記憶する" #: cps/templates/login.html:23 msgid "Forgot Password?" -msgstr "" +msgstr "パスワードを忘れた場合" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" -msgstr "" +msgstr "マジックリンクでログイン" #: cps/templates/logviewer.html:6 msgid "Show Calibre-Web Log: " -msgstr "" +msgstr "Calibre-Webのログを表示: " #: cps/templates/logviewer.html:8 msgid "Calibre-Web Log: " -msgstr "" +msgstr "Calibre-Webのログ: " #: cps/templates/logviewer.html:8 msgid "Stream output, can't be displayed" -msgstr "" +msgstr "ストリームの出力を表示できません" #: cps/templates/logviewer.html:12 msgid "Show Access Log: " -msgstr "" +msgstr "アクセスログを表示: " #: cps/templates/logviewer.html:18 msgid "Download Calibre-Web Log" -msgstr "" +msgstr "Calibre-Webのログをダウンロード" #: cps/templates/logviewer.html:21 msgid "Download Access Log" -msgstr "" +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" -msgstr "" +msgstr "タグを入力" #: cps/templates/modal_dialogs.html:24 msgid "Add View Restriction" -msgstr "" +msgstr "表示制限を追加" #: cps/templates/modal_dialogs.html:50 msgid "This book format will be permanently erased from database" -msgstr "" +msgstr "このファイル形式はDBから完全に削除されます" #: cps/templates/modal_dialogs.html:51 msgid "This book will be permanently erased from database" -msgstr "" +msgstr "この本はDBと" #: cps/templates/modal_dialogs.html:52 msgid "and hard disk" -msgstr "" +msgstr "ローカルから完全に削除されます" #: cps/templates/modal_dialogs.html:56 msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." -msgstr "" +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" -msgstr "" +msgstr "ファイルの場所を選択" #: cps/templates/modal_dialogs.html:82 msgid "type" -msgstr "" +msgstr "種類" #: cps/templates/modal_dialogs.html:83 msgid "name" -msgstr "" +msgstr "名前" #: cps/templates/modal_dialogs.html:84 msgid "size" -msgstr "" +msgstr "サイズ" #: cps/templates/modal_dialogs.html:90 msgid "Parent Directory" -msgstr "" +msgstr "親ディレクトリ" #: cps/templates/modal_dialogs.html:98 msgid "Select" -msgstr "" +msgstr "選択" -#: cps/templates/modal_dialogs.html:134 -#, fuzzy +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" -msgstr "本" +msgstr "OK" #: cps/templates/osd.xml:5 msgid "Calibre-Web eBook Catalog" -msgstr "" +msgstr "Calibre-WebのeBookカタログ" #: cps/templates/read.html:6 msgid "epub Reader" -msgstr "" +msgstr "EPUBリーダー" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "ライト" + +#: 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:75 +#: 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:7 +#: cps/templates/readcbr.html:8 msgid "Comic Reader" -msgstr "" +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:116 -msgid "Light" -msgstr "ライト" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "ダーク" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "管理者ページ" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" -msgstr "サイズ" +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 "" +msgstr "スクロールバー" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" -msgstr "" +msgstr "表示" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" -msgstr "" +msgstr "非表示" #: cps/templates/readdjvu.html:5 msgid "DJVU Reader" -msgstr "" +msgstr "DJVUリーダー" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" -msgstr "" +msgstr "PDFリーダー" #: cps/templates/readtxt.html:6 -#, fuzzy msgid "txt Reader" -msgstr "テキストリーダ" +msgstr "テキストリーダー" #: cps/templates/register.html:4 msgid "Register New Account" -msgstr "" +msgstr "新規アカウントを登録" #: cps/templates/register.html:10 msgid "Choose a username" -msgstr "ユーザ名を入力してください" +msgstr "ユーザー名を入力してください" #: cps/templates/register.html:15 -msgid "Your email address" -msgstr "あなたのメールアドレス" +msgid "Your Email" +msgstr "メールアドレス" #: cps/templates/remote_login.html:5 msgid "Magic Link - Authorise New Device" -msgstr "" +msgstr "マジックリンク - 新規端末を認証する" #: cps/templates/remote_login.html:7 msgid "On another device, login and visit:" -msgstr "" +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 "" +msgstr "この確認リンクの有効期限は10分です。" -#: cps/templates/search.html:5 -msgid "No Results Found" -msgstr "" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "シリーズの表紙サムネイルを生成" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "結果が見つかりません" + +#: cps/templates/search.html:7 msgid "Search Term:" -msgstr "" +msgstr "検索する単語:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "結果:" #: cps/templates/search_form.html:21 msgid "Published Date From" -msgstr "" +msgstr "発売日(〜から)" #: cps/templates/search_form.html:31 msgid "Published Date To" +msgstr "発売日(〜まで)" + +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" msgstr "" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:60 msgid "Exclude Tags" -msgstr "タグを除外" +msgstr "除外するタグ" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" -msgstr "シリーズを除外" +msgstr "除外するシリーズ" -#: cps/templates/search_form.html:95 -#, fuzzy +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" -msgstr "シリーズを除外" +msgstr "除外する本棚" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" -msgstr "言語を除外" +msgstr "除外する言語" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" -msgstr "" +msgstr "拡張子" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" -msgstr "" +msgstr "除外する拡張子" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" -msgstr "" +msgstr "評価(〜以上)" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" -msgstr "" +msgstr "評価(〜以下)" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" -msgstr "" +msgstr "〜から:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" -msgstr "" +msgstr "〜まで:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "この本棚を削除" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" -msgstr "" +msgstr "本棚のプロパティを編集" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" -msgstr "" +msgstr "手動で本を並び替える" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" -msgstr "" +msgstr "並び順の変更を無効にする" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" -msgstr "" +msgstr "並び順の変更を有効にする" #: cps/templates/shelf_edit.html:14 msgid "Share with Everyone" -msgstr "" +msgstr "みんなと共有" #: cps/templates/shelf_edit.html:21 msgid "Sync this shelf with Kobo device" -msgstr "" +msgstr "この本棚をKobo端末と同期" #: cps/templates/shelf_order.html:5 msgid "Drag to Rearrange Order" -msgstr "" +msgstr "ドラッグして並び順を変更" #: cps/templates/shelf_order.html:33 msgid "Hidden Book" -msgstr "" +msgstr "非表示の本" #: cps/templates/stats.html:7 msgid "Library Statistics" -msgstr "" +msgstr "ライブラリの統計" #: cps/templates/stats.html:12 msgid "Books in this Library" -msgstr "このライブラリ内の本" +msgstr "このライブラリ内の本の冊数" #: cps/templates/stats.html:16 msgid "Authors in this Library" -msgstr "このライブラリ内の著者" +msgstr "このライブラリ内の著者数" #: cps/templates/stats.html:20 msgid "Categories in this Library" -msgstr "このライブラリ内のカテゴリ" +msgstr "このライブラリ内のカテゴリ数" #: cps/templates/stats.html:24 msgid "Series in this Library" -msgstr "このライブラリ内のシリーズ" +msgstr "このライブラリ内のシリーズ数" #: cps/templates/stats.html:29 msgid "System Statistics" -msgstr "" +msgstr "システムの統計" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "" +msgid "Program" +msgstr "プログラム" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3054,7 +3331,7 @@ msgstr "インストールされたバージョン" #: cps/templates/tasks.html:12 msgid "User" -msgstr "ユーザ" +msgstr "ユーザー" #: cps/templates/tasks.html:14 msgid "Task" @@ -3070,153 +3347,153 @@ msgstr "進捗" #: cps/templates/tasks.html:17 msgid "Run Time" -msgstr "" +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 "このタスクはキャンセルされます。このタスクによる進捗はすべて保存されます。" + +#: 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 "ユーザパスワードをリセット" +msgstr "パスワードをリセット" #: cps/templates/user_edit.html:43 msgid "Language of Books" -msgstr "" +msgstr "本の言語" #: cps/templates/user_edit.html:54 msgid "OAuth Settings" -msgstr "" +msgstr "OAuth設定" #: cps/templates/user_edit.html:56 msgid "Link" -msgstr "" +msgstr "リンク" #: cps/templates/user_edit.html:58 msgid "Unlink" -msgstr "" +msgstr "リンク解除" #: cps/templates/user_edit.html:64 msgid "Kobo Sync Token" -msgstr "" +msgstr "Kobo同期トークン" #: cps/templates/user_edit.html:66 msgid "Create/View" -msgstr "" +msgstr "作成/表示" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" -msgstr "" +msgstr "強制的にKoboと完全同期" #: cps/templates/user_edit.html:88 msgid "Add allowed/Denied Custom Column Values" -msgstr "" +msgstr "許可/拒否カスタムカラムを追加" #: cps/templates/user_edit.html:137 msgid "Sync only books in selected shelves with Kobo" -msgstr "" +msgstr "選択した本棚内の本のみKoboと同期" #: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 msgid "Delete User" -msgstr "" +msgstr "ユーザーを削除" #: cps/templates/user_edit.html:159 msgid "Generate Kobo Auth URL" -msgstr "" +msgstr "Koboの認証URLを生成" #: cps/templates/user_table.html:80 cps/templates/user_table.html:103 msgid "Select..." -msgstr "" +msgstr "選択..." #: cps/templates/user_table.html:131 msgid "Edit User" -msgstr "" +msgstr "ユーザーを編集" #: cps/templates/user_table.html:134 -#, fuzzy msgid "Enter Username" -msgstr "ユーザ名を入力してください" +msgstr "ユーザー名を入力してください" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "あなたのメールアドレス" +msgid "Enter Email" +msgstr "テストメール" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter Kindle E-mail Address" -msgstr "あなたのメールアドレス" +msgid "Enter eReader Email" +msgstr "E-Readerメールアドレス" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" -msgstr "テストメール" +msgid "eReader Email" +msgstr "E-Readerメール" #: cps/templates/user_table.html:137 -#, fuzzy msgid "Locale" -msgstr "サイズ" +msgstr "地域" #: cps/templates/user_table.html:138 msgid "Visible Book Languages" -msgstr "" +msgstr "表示する本の言語" #: cps/templates/user_table.html:139 msgid "Edit Allowed Tags" -msgstr "" +msgstr "許可タグを編集" #: cps/templates/user_table.html:139 msgid "Allowed Tags" -msgstr "" +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" -msgstr "" +msgstr "許可カスタムカラムを編集" #: cps/templates/user_table.html:141 msgid "Allowed Column Values" -msgstr "" +msgstr "許可カスタムカラム" #: cps/templates/user_table.html:142 msgid "Edit Denied Column Values" -msgstr "" +msgstr "拒否カスタムカラムを編集" #: cps/templates/user_table.html:142 msgid "Denied Column Values" -msgstr "" +msgstr "拒否カスタムカラム" #: cps/templates/user_table.html:144 -#, fuzzy msgid "Change Password" -msgstr "パスワード変更を許可" +msgstr "パスワード変更" #: cps/templates/user_table.html:147 msgid "View" -msgstr "" +msgstr "閲覧" #: cps/templates/user_table.html:150 -#, fuzzy msgid "Edit Public Shelves" -msgstr "本棚を編集する" +msgstr "みんなの本棚を編集" #: cps/templates/user_table.html:152 msgid "Sync selected Shelves with Kobo" -msgstr "" +msgstr "選択した本棚をKoboと同期" #: cps/templates/user_table.html:156 #, fuzzy -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/km/LC_MESSAGES/messages.mo b/cps/translations/km/LC_MESSAGES/messages.mo index 34b973bb..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 795c5861..6eac2f85 100644 --- a/cps/translations/km/LC_MESSAGES/messages.po +++ b/cps/translations/km/LC_MESSAGES/messages.po @@ -8,601 +8,645 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=1; plural=0\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "ស្ថិតិ" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "ម៉ាស៊ីន server បានដំណើរការម្តងទៀត សូមបើកទំព័រជាថ្មី" -#: cps/admin.py:143 -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:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(eReadermail)s ដោយជោគជ័យ" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "ទំព័ររដ្ឋបាល" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "ការកំណត់សាមញ្ញ" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "ការកំណត់ផ្ទាំងប្រើប្រាស់" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "អ្នកប្រើប្រាស់រដ្ឋបាល" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:599 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "ប្តូរការកំណត់ SMTP" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "ទំនាក់ទំនងទៅមូលដ្ឋានទិន្នន័យត្រូវបានផ្តាច់" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "ការកំណត់មុខងារ" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "សូមបំពេញចន្លោះទាំងអស់!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" +#: 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 "" -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "បន្ថែមអ្នកប្រើប្រាស់ថ្មី" - -#: cps/admin.py:1427 +#: cps/admin.py:1323 #, python-format -msgid "User '%(user)s' created" -msgstr "បានបង្កើតអ្នកប្រើប្រាស់ ‘%(user)s’" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1463 +#: cps/admin.py:1326 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានលុប" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "កែប្រែអ្នកប្រើប្រាស់ %(nick)s" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានកែប្រែ" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "ប្តូរការកំណត់ SMTP" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1633 -#, python-format -msgid "There was an error sending the Test e-mail: %(res)s" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." +#: 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:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "កែប្រែអ្នកប្រើប្រាស់ %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "កំពុងស្នើសុំឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "កំពុងទាញយកឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "កំពុងពន្លាឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "ទំនាក់ទំនងទៅមូលដ្ឋានទិន្នន័យត្រូវបានផ្តាច់" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "ការធ្វើបច្ចុប្បន្នភាពបានបញ្ចប់ សូមចុច okay រួចបើកទំព័រជាថ្មី" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 -msgid "not installed" -msgstr "មិនបានតម្លើង" - -#: cps/converter.py:31 -msgid "Execution permissions missing" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +#: cps/admin.py:1730 +msgid "DB is not Writeable" msgstr "" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "គ្មាន" - -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "ទំនាក់ទំនងទៅមូលដ្ឋានទិន្នន័យត្រូវបានផ្តាច់" + +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "ការកំណត់មុខងារ" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "សូមបំពេញចន្លោះទាំងអស់!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" msgstr "" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "កែប្រែទិន្នន័យមេតា" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "បន្ថែមអ្នកប្រើប្រាស់ថ្មី" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +msgid "User '%(user)s' created" +msgstr "បានបង្កើតអ្នកប្រើប្រាស់ ‘%(user)s’" + +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1956 #, python-format -msgid "'%(langname)s' is not a valid language" +msgid "User '%(nick)s' deleted" +msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានលុប" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" msgstr "" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: 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:2043 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "ឯកសារប្រភេទ '%(ext)s' មិនត្រូវបានអនុញ្ញាតឲអាប់ឡូដទៅម៉ាស៊ីន server នេះទេ" +msgid "User '%(nick)s' updated" +msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានកែប្រែ" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "ឯកសារដែលត្រូវអាប់ឡូដត្រូវមានកន្ទុយឯកសារ" +#: cps/converter.py:31 +msgid "not installed" +msgstr "មិនបានតម្លើង" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "មិនអាចបង្កើតទីតាំង %(path)s (ពុំមានសិទ្ធិ)។" +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "" -#: cps/editbooks.py:660 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Failed to store file %(file)s." -msgstr "មិនអាចរក្សាទុកឯកសារ %(file)s ។" +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "" -#: cps/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "ឯកសារទម្រង់ %(ext)s ត្រូវបានបន្ថែមទៅ %(book)s" +#: 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 "គ្មាន" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "" + +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "ឯកសារដែលត្រូវអាប់ឡូដត្រូវមានកន្ទុយឯកសារ" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:1117 -#, python-format -msgid "File %(file)s uploaded" +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:1151 -#, python-format -msgid "Book successfully queued for converting to %(book_format)s" +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "កែប្រែទិន្នន័យមេតា" + +#: cps/editbooks.py:992 #, python-format -msgid "There was an error converting this book: %(res)s" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "មិនអាចបង្កើតទីតាំង %(path)s (ពុំមានសិទ្ធិ)។" + +#: cps/editbooks.py:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "មិនអាចរក្សាទុកឯកសារ %(file)s ។" + +#: 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 "" @@ -616,185 +660,178 @@ msgstr "Callback domain មិនទាន់បានផ្ទៀងផ្ទ 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "ផ្ញើទៅ Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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 "" -#: cps/helper.py:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +msgid "Test Email" msgstr "" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" -msgstr "" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" +msgstr "ផ្ញើទៅ Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "ផ្ញើទៅ Kindle" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "ឯកសារដែលបានស្នើសុំមិនអាចបើកបានទេ។ អាចនឹងខុសសិទ្ធិប្រើប្រាស់ទេដឹង?" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "ទីតាំងសៀវភៅ %(path)s រកមិនឃើញក្នុង Google Drive" -#: cps/helper.py:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "កំពុងរង់ចាំ" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "បានបរាជ័យ" - -#: cps/helper.py:941 -msgid "Started" -msgstr "បានចាប់ផ្តើម" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "បានបញ្ចប់" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "ស្រាវជ្រាវ" -#: cps/helper.py:945 -msgid "Unknown Status" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -803,9 +840,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1613 +#: 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 @@ -864,12 +901,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "ចូលប្រើប្រាស់" @@ -885,496 +923,613 @@ msgstr "វត្ថុតាងហួសពេលកំណត់" msgid "Success! Please return to your device" msgstr "ជោគជ័យ! សូមវិលមកឧបករណ៍អ្នកវិញ" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "បង្ហាញសៀវភៅមកថ្មី" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "សៀវភៅដែលមានប្រជាប្រិយភាព" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "បង្ហាញសៀវភៅដែលមានប្រជាប្រិយភាព" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "សៀវភៅដែលមានការវាយតម្លៃល្អជាងគេ" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "បង្ហាញអានរួច និងមិនទាន់អាន" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "ស្រាវជ្រាវ" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "ស្វែងរក" + +#: cps/search.py:188 +msgid "Published after " +msgstr "បានបោះពុម្ភក្រោយ " + +#: cps/search.py:195 +msgid "Published before " +msgstr "បានបោះពុម្ភមុន " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "ការវាយតម្លៃ <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "ការវាយតម្លៃ >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "ស្វែងរកកម្រិតខ្ពស់" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "សូមអភ័យទោស អ្នកមិនមានសិទ្ធិដកសៀវភៅចេញពីធ្នើនេះទេ៖ %(sname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "សៀវភៅត្រូវបានបន្ថែមទៅធ្នើ៖ %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "សៀវភៅត្រូវបានដកចេញពីធ្នើ៖ %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "បង្កើតធ្នើ" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "សូមអភ័យទោស អ្នកមិនមានសិទ្ធិដកសៀវភៅចេញពីធ្នើនេះទេ៖ %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "កែប្រែធ្នើ" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "ប្តូរលំដាប់ធ្នើ៖ ‘%(name)s’" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "ធ្នើឈ្មោះ %(title)s ត្រូវបានបង្កើត" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "ធ្នើឈ្មោះ %(title)s ត្រូវបានប្តូរ" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "មានបញ្ហា" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "ធ្នើ៖ ‘%(name)s’" -#: cps/shelf.py:339 -msgid "Shelf successfully deleted" -msgstr "" +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "មានបញ្ហាពេលបើកធ្នើ។ ពុំមានធ្នើ ឬមិនអាចបើកបាន" -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "ប្តូរលំដាប់ធ្នើ៖ ‘%(name)s’" +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "កិច្ចការនានា" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "កំពុងរង់ចាំ" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "បានបរាជ័យ" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "បានចាប់ផ្តើម" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "បានបញ្ចប់" -#: cps/shelf.py:461 -#, python-format -msgid "Shelf: '%(name)s'" -msgstr "ធ្នើ៖ ‘%(name)s’" +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" -#: cps/shelf.py:465 -msgid "Error opening shelf. Shelf does not exist or is not accessible" -msgstr "មានបញ្ហាពេលបើកធ្នើ។ ពុំមានធ្នើ ឬមិនអាចបើកបាន" +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: 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 "" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "ស្រាវជ្រាវ (សៀវភៅចៃដន្យ)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "សៀវភៅដែលត្រូវបានទាញយកច្រើនជាងគេ" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "ស៊េរី៖ %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "ប្រភេទ៖ %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "ភាសា៖ %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "ស្វែងរកកម្រិតខ្ពស់" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "ស្វែងរក" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "ឯកសារ DLS" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "កិច្ចការនានា" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "បានបោះពុម្ភក្រោយ " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "បានបោះពុម្ភមុន " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "ការវាយតម្លៃ <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "ការវាយតម្លៃ >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "សូមកំណត់អ៊ីមែល SMTP ជាមុនសិន" -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(kindlemail)s ដោយជោគជ័យ" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(eReadermail)s ដោយជោគជ័យ" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: 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:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "ខុសឈ្មោះអ្នកប្រើប្រាស់ ឬលេខសម្ងាត់" -#: cps/web.py:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1644 -msgid "Please enter valid username to reset password" +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." msgstr "" -#: cps/web.py:1651 -#, python-format +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "ខុសឈ្មោះអ្នកប្រើប្រាស់ ឬលេខសម្ងាត់" + +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "" +msgstr "ឥឡូវអ្នកបានចូលដោយមានឈ្មោះថា៖ ‘%(nickname)s’" -#: cps/web.py:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Ebook-converter បានបរាជ័យ៖ %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "កែប្រែទិន្នន័យមេតា" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "អាប់ឡូដ" + #: cps/templates/admin.html:9 msgid "Users" msgstr "បញ្ជីអ្នកប្រើប្រាស់" @@ -1387,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "ឧបករណ៍ Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "រដ្ឋបាល" @@ -1404,13 +1560,8 @@ msgstr "រដ្ឋបាល" msgid "Password" msgstr "លេខសម្ងាត់" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "អាប់ឡូដ" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "ទាញយក" @@ -1424,7 +1575,7 @@ msgstr "" msgid "Edit" msgstr "កែប្រែ" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1435,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 @@ -1465,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 @@ -1537,78 +1684,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "ភ្ជាប់ទៅ database Calibre ម្តងទៀត" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:178 -msgid "Update" +#: cps/templates/admin.html:221 +msgid "Version Information" msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "រកមើលបច្ចុប្បន្នភាព" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "ធ្វើបច្ចុប្បន្នភាព" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "កំពុងធ្វើបច្ចុប្បន្នភាព សូមកុំបើកទំព័រជាថ្មី" @@ -1620,39 +1798,39 @@ msgstr "តាមរយៈ" msgid "In Library" msgstr "នៅក្នុងបណ្ណាល័យ" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "" @@ -1660,165 +1838,166 @@ msgstr "" msgid "More by" msgstr "បន្ថែមទៀតដោយ" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "លុបសៀវភៅ" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "លុបឯកសារទម្រង់៖" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "ចំណងជើងសៀវភៅ" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "អ្នកនិពន្ធ" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "ពិពណ៌នា" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tag" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "លេខសម្គាល់ស៊េរី" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "ការវាយតម្លៃ" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "URL របស់ក្របមុខ (ឯកសារ JPG ក្របមុខត្រូវបានទាញយក និងរក្សាទុកក្នុង database ក្រោយមកចន្លោះនេះទទេម្តងទៀត)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "ថ្ងៃបោះពុម្ភ" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "អ្នកបោះពុម្ភ" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "ទេ" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "ទម្រង់អាប់ឡូដ" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "មើលសៀវភៅក្រោយពីកែប្រែ" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "មើលទិន្នន័យមេតា" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "ពាក្យគន្លឹះ" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr "ស្វែងរកពាក្យគន្លឹះ" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "ចុចលើគម្របដើម្បីបញ្ចូលទិន្នន័យមេតាទៅក្នុង form" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "កំពុងដំណើរការ..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "បិទ" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "ប្រភព" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "ការស្វែងរកមានកំហុស!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "" @@ -1910,7 +2089,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1926,6 +2105,7 @@ 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 "" @@ -2030,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 @@ -2046,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 @@ -2236,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 "មើលការកំណត់" @@ -2248,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 "ការតុបតែង" @@ -2339,79 +2563,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "អានក្នុងកម្មវិធី browser" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "អាន" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "ពិពណ៌នា" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "បន្ថែមទៅធ្នើ" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2435,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:29 +#: 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 "មកក្រោយ" @@ -2464,186 +2691,194 @@ msgstr "" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "បិទ/បើកការរុករក" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "កំពុងអាប់ឡូត..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "" -#: cps/templates/layout.html:76 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 "ការកំណត់" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "ចេញពីការប្រើប្រាស់" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "រុករក" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "អំពី" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "មុន" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "ព័ត៌មានលម្អិតរបស់សៀវភៅ" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "ចងចាំខ្ញុំ" @@ -2652,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" @@ -2748,7 +2983,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "សៀវភៅ" @@ -2761,127 +2996,161 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "មកក្រោយ" + +#: 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:116 -msgid "Light" +#: cps/templates/readcbr.html:110 +msgid "Display" msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "ទំព័ររដ្ឋបាល" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" msgstr "" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2889,7 +3158,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -2907,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 @@ -2926,15 +3195,19 @@ msgstr "ក្រោយពីនេះ អ្នកនឹងត្រូវប msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "លទ្ធផលសម្រាប់៖" @@ -2946,64 +3219,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "លុបធ្នើនេះ" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3048,8 +3329,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Library របស់កម្មវិធី" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3075,9 +3356,17 @@ 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 "" + +#: 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" @@ -3143,17 +3432,18 @@ msgstr "ជ្រើសរើសឈ្មោះអ្នកប្រើប្រ #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "អាសយដ្ឋានអ៊ីមែលរបស់អ្នក" +msgid "Enter Email" +msgstr "ឧបករណ៍ Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "ឧបករណ៍ Kindle" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "" +#, fuzzy +msgid "eReader Email" +msgstr "ឧបករណ៍ Kindle" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3215,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 e85e6720..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 31402b0f..ac395626 100644 --- a/cps/translations/ko/LC_MESSAGES/messages.po +++ b/cps/translations/ko/LC_MESSAGES/messages.po @@ -6,593 +6,637 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: 내맘대로의 epubguide.net \n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "통계" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "서버 다시 시작으로 새로고침 필요" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "서버를 종료하는 중, 창을 닫아야 함" -#: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "재연결 성공" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "성공적으로 DB를 다시 연결하였습니다." -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "알 수 없는 명령" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "%(email)s에 테스트를 위한 이메일을 보냄. 결과 확인 필요" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "관리자 페이지" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "기본 설정" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI 설정" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "사용자 관리" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "모두" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "사용자를 찾을 수 없음" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} 사용자를 성공적으로 삭제함" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "잘못된 요청" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Guest 이름은 수정할 수 없음" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Guest는 이 권한을 사용할 수 없음" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "관리자 계정이 하나 뿐일 때는 관리자를 삭제할 수 없음" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "값으로 rue 또는 false만 설정 가능" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "잘못된 권한" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Guest는 이 view를 사용할 수 없음" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "잘못된 view" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Guest의 로케일은 자동으로 결정되며 설정할 수 없음" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "유효한 로케일이 아님" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "제공된 책의 언어가 유효하지 않음" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "매개변수를 찾을 수 없음" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "잘못된 읽기 열" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "잘못된 제한된 열" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web 설정이 업데이트 됨" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Kobo Token을 삭제하시겠습니까?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "이 도메인을 삭제하시겠습니까?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "이 사용자를 삭제하시겠습니까?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "이 서재를 삭제하시겠습니까?" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "선택한 사용자의 언어를 변경하시겠습니까?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "선택한 사용자에 대해 표시되는 책 언어를 변경하시겠습니까?" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "선택한 사용자에 대해 선택한 권한을 변경하시겠습니까?" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "선택한 사용자에 대해 선택한 제한을 변경하시겠습니까?" -#: cps/admin.py:607 +#: 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:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "선택한 사용자의 실행기 동기화 동작을 변경하시겠습니까?" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "캘리버 서재의 언어를 변경하시겠습니까?" -#: cps/admin.py:614 +#: 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: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:764 -msgid "Tag not found" -msgstr "태그를 찾을 수 없음" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "잘못된 액션" - -#: cps/admin.py:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} 동기화 항목이 삭제됨" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "태그를 찾을 수 없음" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "잘못된 액션" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json이 Web 응용프로그램에 대해 설정되지 않음" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "로그 파일 위치가 오류. 올바른 경로 입력 필요" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "액세스 로그 파일 위치가 올바르지 않음. 올바른 경로 입력 필요" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "LDAP 공급자, 포트, DN 및 사용자 개체 식별자를 입력" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "LDAP 서비스 계정 및 비밀번호를 입력하십시오" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "LDAP 서비스 계정을 입력하십시오" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP 그룹 개체 필터에는 하나의 \"%s\" 형식 식별자가 필요함" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP 그룹 개체 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP 사용자 개체 필터에는 하나의 \"%s\" 형식 식별자 필요" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP 사용자 개체 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP 구성원 사용자 필터에는 하나의 \"%s\" 형식 식별자 필요" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP 구성원 사용자 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "유요하지 않은 LDAP CACertificate, 인증서 또는 키 위치. 올바른 경로를 입력 필요" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "데이터베이스 오류: %(error)s." - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "올바르지 않은 DB 위치. 올바른 경로 입력 필요" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "쓰기 권한이 없는 DB" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "올바르지 않은 키 파일 위치. 올바른 경로 입력 필요" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "올바르지 않은 인증서 파일 위치. 올바른 경로 입력 필요" - -#: cps/admin.py:1378 -msgid "Database Settings updated" -msgstr "데이터베이스 설정이 업데이트 되었습니다" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "데이터베이스 구성" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "모든 필드를 채워주십시오!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "유효한 도메인에서 온 이메일이 아니" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "새 사용자 추가" - -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "사용자 '%(user)s'이(가) 생성됨" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "동일한 이메일 주소 또는 이름이 이미 등록되어 있습니다." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "사용자 '%(nick)s'이(가) 삭제됨" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "게스트 사용자는 삭제할 수 없습니다" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "사용자 추가" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "관리자 계정이 하나 뿐일 때는 관리자 권한을 삭제할 수 없음" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "이메일 서버 설정 편집" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "사용자 %(nick)s 편집" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gmail 계정 인증에 성공하였습니다." -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "사용자 '%(nick)s'가 업데이트 됨" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "알 수없는 오류가 발생했습니다. 나중에 다시 시도 해주십시오." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "이메일 서버 설정 편집" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "Gmail 계정 인증 성공" +msgid "Oops! Database Error: %(error)s." +msgstr "데이터베이스 오류: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "테스트 이메일을 보내는 동안 오류가 발생했습니다: %(res)s" -#: cps/admin.py:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "먼저 이메일 주소를 구성하십시오..." -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "이메일 서버 설정 업데이트됨" -#: cps/admin.py:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "예약 작업 설정 편집" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "지정된 작업의 시작 시간이 잘못 설정되었습니다." + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "지정된 작업의 기간이 잘못 설정되었습니다." + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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:1394 +msgid "Settings DB is not Writeable" +msgstr "저장할 수 없는 설정 DB입니다." + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "사용자 %(nick)s 편집" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "사용자 %(user)s의 비밀번호 재설정" -#: cps/admin.py:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "로그 파일 뷰어" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "업데이트 패키지 요청" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "업데이트 패키지 다운로드" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "업데이트 패키지 압축 풀기" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "파일 교체" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "데이터베이스 연결이 닫힙니다" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "서버 중지" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "업데이트가 완료되었습니다. 확인을 누르고 페이지를 새로고침하세요" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP 오류" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "연결 오류" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "연결 설정 중 시간 초과" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "일반 오류" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "임시 디렉토리에 업데이트 파일을 저장할 수 없습니다" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "업데이트하는 동안 파일을 교체할 수 없습니다" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "하나 이상의 LDAP 사용자를 추출하지 못했습니다" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "하나 이상의 LDAP 사용자를 생성하지 못했습니다" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "오류: %(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "오류: LDAP 서버의 응답으로 사용자가 반환되지 않았습니다" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "데이터베이스에서 하나 이상의 LDAP 사용자를 찾을 수 없습니다" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 사용자 가져오기 성공" -#: cps/converter.py:30 -msgid "not installed" -msgstr "설치되지 않음" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "올바르지 않은 DB 위치. 올바른 경로 입력 필요" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "실행 권한 누락" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "쓰기 권한이 없는 DB" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "사용자 정의 열 번호 %(column)d이(가) calibre 데이터베이스에 없습니다" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "올바르지 않은 키 파일 위치. 올바른 경로 입력 필요" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "None" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "올바르지 않은 인증서 파일 위치. 올바른 경로 입력 필요" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "책 형식이 성공적으로 삭제되었습니다" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "비밀번호 길이는 1에서 40 사이여야 합니다." -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "책이 성공적으로 삭제되었습니다" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "데이터베이스 설정이 업데이트 되었습니다" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "데이터베이스 구성" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "선택한 책 제목을 사용할 수 없습니다. 파일이 존재하지 않거나 액세스할 수 없습니다" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "모든 필드를 채워주십시오!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "메타데이터 편집" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "유효한 도메인에서 온 이메일이 아니" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s은(는) 유효한 숫자가 아닙니다. 건너뜁니다" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "새 사용자 추가" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1920 #, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "'%(langname)s'은(는) 유효한 언어가 아닙니다" +msgid "User '%(user)s' created" +msgstr "사용자 '%(user)s'이(가) 생성됨" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" -msgstr "" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "동일한 이메일 주소 또는 이름이 이미 등록되어 있습니다." -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "파일 확장자 '%(ext)s'은(는) 이 서버에 업로드할 수 없습니다" +msgid "User '%(nick)s' deleted" +msgstr "사용자 '%(nick)s'이(가) 삭제됨" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "업로드할 파일에는 확장자가 있어야 합니다" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "게스트 사용자는 삭제할 수 없습니다" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "%(path)s 경로를 생성하지 못했습니다(권한이 없음)." +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "관리자 계정이 하나 뿐일 때는 관리자 권한을 삭제할 수 없음" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "%(file)s 파일을 저장하지 못했습니다." +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "이메일은 반드시 입력해야 하며 유효한 이메일이어야 합니다." -#: cps/editbooks.py:683 +#: cps/admin.py:2043 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "파일 형식 %(ext)s이(가) %(book)s에 추가되었습니다" +msgid "User '%(nick)s' updated" +msgstr "사용자 '%(nick)s'가 업데이트 됨" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "설치되지 않음" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "실행 권한 누락" + +#: 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: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 "None" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "표지를 업로드 할 수 있는 권한이 없는 사용자입니다." -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "식별자는 대소문자를 구분하지 않으며 이전 식별자를 덮어씁니다" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "메타데이터가 성공적으로 업데이트되었습니다" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "책 편집 중 오류 발생: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "파일 %(file)s 업로드됨" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "변환을 위한 소스 또는 대상 형식이 누락되었습니다" -#: cps/editbooks.py:951 +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "책이 %(book_format)s(으)로 변환하기 위해 대기 중입니다" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "이 책을 변환하는 동안 오류가 발생했습니다: %(res)s" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "업로드한 책이 라이브러리에 있을 수 있음. 새로 업로드하기 전에 확인 필요: " -#: cps/editbooks.py:1041 +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s'은(는) 유효한 언어가 아닙니다" + +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "업로드할 파일에는 확장자가 있어야 합니다" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "파일 %(filename)s을(를) 임시 디렉토리에 저장할 수 없습니다" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "표지 파일%(file)s를 이동하지 못했습니다.:%(error)s" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "책 형식이 성공적으로 삭제되었습니다" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "책이 성공적으로 삭제되었습니다" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "책을 삭제할 수 있는 권한이 없습니다." + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "메타데이터 편집" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "파일 %(file)s 업로드됨" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s은(는) 유효한 숫자가 아닙니다. 건너뜁니다" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "변환을 위한 소스 또는 대상 형식이 누락되었습니다" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "추가 파일 유형을 업로드 할 권한이 없는 사용자입니다." -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "책이 %(book_format)s(으)로 변환하기 위해 대기 중입니다" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "%(path)s 경로를 생성하지 못했습니다(권한이 없음)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "이 책을 변환하는 동안 오류가 발생했습니다: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "%(file)s 파일을 저장하지 못했습니다." + +#: 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" @@ -607,186 +651,184 @@ msgstr "콜백 도메인이 확인되지 않았습니다. 단계에 따라 Googl 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "킨들로 보내기" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web 테스트 이메일" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "테스트 이메일" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Web 시작하기" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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로 변환하고 킨들로 보내기" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "킨들에 %(format)s 보내기" -#: cps/helper.py:220 cps/tasks/convert.py:92 -#, python-format -msgid "%(book)s send to Kindle" +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" msgstr "%(book)s을 킨들로 보내기" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "요청한 파일을 읽을 수 없습니다. 올바른 권한인가요?" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "읽기 상태를 설정할 수 없음: {}" -#: cps/helper.py:376 +#: 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:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "%(id)s 도서 삭제 실패: %(message)s" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "경로에서 파일 이름을 바꾸는 중 오류가 발생: {}" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Google 드라이브에서 책 경로 %(path)s을(를) 찾을 수 없습니다" -#: cps/helper.py:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "등록되어 있는 username입니다" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "이메일 주소 형식이 잘못되었습니다" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" -msgstr "" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "규칙에 어긋나는 비밀번호입니다." -#: cps/helper.py:767 +#: 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:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "표지 형식 오류" -#: cps/helper.py:773 +#: 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:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "표지 경로 생성 실패" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "표지 파일이 유효한 이미지 파일이 아니거나 저장할 수 없습니다" -#: cps/helper.py:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "잘못된 표지 파일 콘텐츠" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "표지 파일로 jpg/jpeg 파일만 지원됩니다" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar 바이너리 파일을 찾을 수 없습니다" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "UnRar 실행 오류" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "대기중" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "실패" - -#: cps/helper.py:941 -msgid "Started" -msgstr "시작됨" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "종료" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "발견" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "알 수 없는 상태" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "메타데이터 백업을 위해 모든 도서를 대기열에 추가" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 설정" @@ -795,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:1613 +#: 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 @@ -856,12 +898,13 @@ msgstr "Google 인증 오류입니다. 나중에 다시 시도하세요." msgid "Google Oauth error: {}" msgstr "Google 인증 오류: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Stars" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "로그인" @@ -877,495 +920,616 @@ msgstr "토큰이 만료되었습니다" msgid "Success! Please return to your device" msgstr "성공! 기기로 돌아가주세요" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "책" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "최근 책 보기" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "인기있는 책" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "주목받는 책 보기" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "다운로드된 책" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "평점이 높은 책" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "읽은 책과 읽지 않은 책 보기" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "읽지 않은 책 보기" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "발견" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "평점" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "파일 유형" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "보관된 책" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "책 목록" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "책 목록 보기" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "검색" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Published after " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Published before " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "평점 <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "평점 >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "읽은 상태 = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "사용자 정의 열을 검색하는 동안 오류가 발생했습니다. Calibre-Web을 다시 시작하십시오" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "상세 검색" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "잘못된 책장 지정" -#: cps/shelf.py:73 +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" msgstr "죄송합니다. 해당 책장에 책을 추가할 권한이 없습니다" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "책이 이미 책장에 등록됨: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "책장에 책이 등록됨: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "책장에 책을 추가할 권한이 없습니다" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "책장에 이미 책이 등록됨: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "책이 책장에 등록됨: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "책장에 책을 추가할 수 없음: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "책이 책장에서 삭제됨: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "죄송합니다. 이 서가에서 책을 삭제할 권한이 없습니다" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "책장 추가" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" msgstr "죄송합니다. 이 책장을 편집할 권한이 없습니다" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "책장 편집" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "서제를 삭제하는 동안 오류 발생" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "책이 성공적으로 삭제되었습니다" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "책장 순서 변경: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "죄송합니다. 이 공개 책장을 만들 권한이 없습니다" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s 책장이 추가됨" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s 책장이 변경됨" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "오류가 발생하였습니다" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." -msgstr "이름이 '%(title)s'인 공개 책장이 이미 있습니다." - -#: cps/shelf.py:315 -#, python-format -msgid "A private shelf with the name '%(title)s' already exists." -msgstr "이름이 '%(title)s'인 개인 책장이 이미 있습니다." - -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "책이 성공적으로 삭제되었습니다" +msgstr "이름이 '%(title)s'인 공개 책장이 이미 있습니다." -#: cps/shelf.py:389 +#: cps/shelf.py:383 #, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "책장 순서 변경: '%(name)s'" +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "이름이 '%(title)s'인 개인 책장이 이미 있습니다." -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "책장: '%(name)s'" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "책장을 여는 동안 오류가 발생했습니다. 책장이 존재하지 않거나 접근할 수 없습니다" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "작업" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "대기중" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "실패" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "시작됨" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "종료" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "종료됨" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "취소됨" + +#: 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 "업데이트 정보를 읽는 동안 예기치 않은 데이터" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "업데이트가 없습니다. 이미 최신 버전이 설치되어 있습니다" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "새로운 업데이트가 있습니다. 아래 버튼을 클릭하여 최신 버전으로 업데이트하십시오." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "업데이트 정보를 가져올 수 없습니다" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "새로운 업데이트가 있습니다. 아래 버튼을 클릭하여 최신 버전으로 업데이트하십시오." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "최신 안정 버전 %(version)s으로 업데이트하려면 아래 버튼을 클릭하세요" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "출시 정보가 없습니다" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "발견(무작위 도서)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "인기있는 책(가장 많이 다운로드됨)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s이(가) 다운로드한 책" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "저자: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "출판사: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "시리즈: %(serie)s" -#: cps/web.py:610 +#: 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:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "파일 유형: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "카테고리: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "언어: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "상세 검색" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "검색" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "다운로드" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "평점 목록" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "파일 유형 목록" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "작업" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Published after " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Published before " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "평점 <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "평점 >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "읽은 상태 = %(status)s" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "사용자 정의 열을 검색하는 동안 오류가 발생했습니다. Calibre-Web을 다시 시작하십시오" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "먼저 SMTP 메일 설정을 구성하십시오..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "성공적으로 %(kindlemail)s에 보내기 예약이 되었습니다" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "성공적으로 %(eReadermail)s에 보내기 예약이 되었습니다" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP 인증을 활성화할 수 없습니다" -#: cps/web.py:1621 -#, 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:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "로그인 실패: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "잘못된 사용자명 또는 비밀번호" -#: cps/web.py:1638 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "새 비밀번호가 이메일로 전송되었습니다" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Calibre ebook-convert %(tool)s을(를) 찾을 수 없습니다" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s 형식을 찾을 수 없습니다" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "알 수 없는 오류로 인해 전자책 변환이 실패했습니다" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify 변환 실패: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "변환된 파일을 찾을 수 없거나 %(folder)s 폴더에 하나 이상의 파일이 존재합니다" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "\"전자책 변환 실패: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "오류로 인한 Calibre 실패: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "변환" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Calibre DB를 다시 연결합니다." + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "이메일일" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "메타데이터 편집" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "%(count)개의 표지 섬네일을 생성하였습니다." + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "표지 섬네일" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "{0} 시리즈 섬네일을 생성하였습니다." + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "업로드" + #: cps/templates/admin.html:9 msgid "Users" msgstr "사용자" @@ -1378,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "킨들로 보내기 이메일 주소" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "관리자" @@ -1395,13 +1560,8 @@ msgstr "관리자" msgid "Password" msgstr "비밀번호" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "업로드" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "다운로드" @@ -1415,7 +1575,7 @@ msgstr "책 보기" msgid "Edit" msgstr "편집" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1426,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 @@ -1456,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" @@ -1527,80 +1684,111 @@ msgstr "기본 환경 설정 편집" msgid "Edit UI Configuration" msgstr "UI 환경 설정 편집" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "예약된 작업" + +#: 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 +msgid "Maximum Duration" +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 "시리즈 표지 섬네일 생성" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Debug Package 다운로드" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "로그 보기" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Calibre DB 다시 연결" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "재시작" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "종료" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "업데이트" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "버전 정보" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "버전" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "세부 정보" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "현재 버전" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "업데이트 확인" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "업데이트 실행" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "재시작을 하시겠습니까?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "종료를 하시겠습니까?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" -msgstr "Встановлення оновлень, будь-ласка, не оновлюйте сторінку" +msgstr "업데이트 중입니다. 이 페이지를 새로고침 하지 마세요." #: cps/templates/author.html:15 msgid "via" @@ -1610,39 +1798,39 @@ msgstr "via" msgid "In Library" msgstr "In Library" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "책 목록 정렬, 최신순" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "책 목록 정렬, 오래된 순" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "가나다 순 정렬" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "가나다 역순 정렬" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "발행일 순으로 정렬, 최신순" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "발행일 순으로 정렬, 오래된 순" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "reduce" @@ -1650,164 +1838,165 @@ msgstr "reduce" msgid "More by" msgstr "More by" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "책 삭제" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "유형 삭제:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "책 유형 변경:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "변경전 유형:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "옵션 선택" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "변경후 유형:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "책 변경" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "책 제목" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "저자" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "책 소개" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "식별자" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "식별자 유형" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "식별자 값" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "삭제" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "식별자 추가" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "태그" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "시리즈 ID" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "평점" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "URL로 표지 추가(JPEG - 이미지를 다운로드 하여 DB에 저장합니다)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "로컬 디스크에서 표지 업로드" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "출간일" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "출판사" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "아니오" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "업로드 유형" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "저장 후 책 보기" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "메타정보 가져오기" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "저장" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "키워드" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 msgid "Search keyword" msgstr "키워드 검색" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "표지를 클릭하여 양식에 메타데이터 로드" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "불러오는 중..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "닫기" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "출처" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "오류 검색!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "검색 결과가 없습니다! 다른 키워드를 시도하십시오." @@ -1899,8 +2088,8 @@ msgid "Comments" msgstr "코멘트" #: cps/templates/book_table.html:75 -msgid "Archiv Status" -msgstr "" +msgid "Archive Status" +msgstr "아카이브 상태태" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" @@ -1914,6 +2103,7 @@ 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 "정말 확신합니까?" @@ -1943,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" @@ -2018,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 @@ -2034,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 @@ -2224,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 "환경 설정 보기" @@ -2236,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 "테마" @@ -2325,80 +2561,84 @@ msgstr "허용/거부 태그 추가" msgid "Add Allowed/Denied custom column values" msgstr "허용/거부 사용자 정의 열 값 추가" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "부라우저에서 보기" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "브라우저에서 듣기" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "출간일" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "읽지 않은 상태로 표시" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "읽은 상태로 표시" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "읽기" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "아카이브에서 복원" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "아카이브에 추가" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "보관됨" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "설명:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "서재에 추가" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2421,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:29 +#: 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 "뒤로" @@ -2450,187 +2691,195 @@ msgstr "도메인 입력" msgid "Denied Domains (Blacklist)" msgstr "거부 도메인(블랙리스트)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "코보 연동 토큰" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "목록" + +#: 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 "로그아웃" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "다운로드 횟수에 따라 오름차순 정렬" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "다운로드 횟수에 따라 내림차순 정렬" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "저자를 가나다순(알파벳순)으로 정렬" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "저자를 가나다(알파벳) 역순으로 정렬" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "시리즈 인덱스에 따라 오름차순 정렬" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "홈" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "탐색 활성화" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "검색" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "업로드 중..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "오류" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "업로드 완료, 처리 중입니다. 잠시만 기다려 주십시오..." -#: cps/templates/layout.html:76 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 "설정" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "계정" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "로그아웃" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "페이지를 새로고침 하지 마세요" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "탐색" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "서재 정보" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "이전" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "책 상세정보" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "그리드드" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "로그인 유지" @@ -2639,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로 로그인" @@ -2735,7 +2984,7 @@ msgstr "상위 폴더" msgid "Select" msgstr "선택" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "Ok" @@ -2747,127 +2996,161 @@ msgstr "Calibre-Web 책 목록" msgid "epub Reader" msgstr "epub 리더" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "밝게" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "뒤로" + +#: 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:116 -msgid "Light" -msgstr "밝게" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "화면" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "어둡게" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "관리자 페이지" -#: cps/templates/readcbr.html:122 +#: 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 "숨기기" @@ -2875,7 +3158,7 @@ msgstr "숨기기" msgid "DJVU Reader" msgstr "DJVU 리더" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDF 리더" @@ -2892,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 @@ -2911,15 +3194,19 @@ msgstr "승인이 되면 이 장치에 자동으로 로그인됩니다." msgid "This verification link will expire in 10 minutes." msgstr "이 확인 링크는 10분 후에 만료됩니다." -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "시리즈 섬네일 표지 생성" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "결과 없음" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "검색어:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "결과:" @@ -2931,63 +3218,71 @@ 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 "까지:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "이 서재 삭제" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "서재 속성 편집" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "수동으로 책 정렬" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "정렬 변경 비활성화" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "정렬 변경 활성화" @@ -3032,8 +3327,8 @@ msgid "System Statistics" msgstr "시스템 통계" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "서재 프로그램" +msgid "Program" +msgstr "프로그램램" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3059,9 +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 "Actions" + +#: 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" @@ -3124,16 +3427,19 @@ 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 Kindle E-mail Address" -msgstr "킨들 이메일 주소 입력" +#, fuzzy +msgid "Enter eReader Email" +msgstr "킨들로 보내기 이메일 주소" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "킨들 이메일" +#, fuzzy +msgid "eReader Email" +msgstr "테스트 이메일" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3192,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 589137d9..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 a8bd8632..5f9907ee 100644 --- a/cps/translations/nl/LC_MESSAGES/messages.po +++ b/cps/translations/nl/LC_MESSAGES/messages.po @@ -8,603 +8,647 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web (GPLV3)\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" +"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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistieken" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Opnieuw verbinden gelukt" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Gelukt! Database opnieuw verbonden" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Onbekende opdracht" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Systeembeheer" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Basisconfiguratie" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Uiterlijk aanpassen" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Systeembeheerder" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Gebruiker niet gevonden" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} gebruikers succesvol verwijderd" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Misvormd verzoek" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gast kan deze rol niet hebben" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ongeldige rol" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gast kan dit niet bekijken" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ongeldige waarde" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Geen geldige locale is opgegeven" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Geen geldige boek taal is opgegeven" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter is niet gevonden" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Ongeldige gelezen kolom" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Ongeldige beperkte kolom" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web-configuratie bijgewerkt" -#: cps/admin.py:591 +#: 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:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Wil je dit domein echt verwijderen?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Wil je deze gebruiker echt verwijderen?" -#: cps/admin.py:597 +#: 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:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -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:764 -msgid "Tag not found" -msgstr "Tag niet gevonden" +#: cps/admin.py:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "Calibre-web gaat zoeken naar bijgewerkte omslagen en miniaturen bijwerken, dit kan even duren?" -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Ongeldige actie" +#: 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 "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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "" +msgstr "{} synchronisatie objecten verwijderd" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Tag niet gevonden" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Ongeldige actie" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Voer een LDAP Service Account in" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP Gebruiker Filter heeft een niet-gebalanceerd haakje" -#: cps/admin.py:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Database fout: %(error)s." - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "Database niet gevonden, voer de juiste locatie in" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "Kan niet schrijven naar database" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "SSL-sleutellocatie is niet geldig, voer een geldig pad in" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "SSL-certificaatlocatie is niet geldig, voer een geldig pad in" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "E-mailserver-instellingen bijgewerkt" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Databaseconfiguratie" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Vul alle velden in!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "Het e-mailadres bevat geen geldige domeinnaam" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Gebruiker toevoegen" -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Gebruiker '%(user)s' aangemaakt" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Bestaand account met dit e-mailadres of deze gebruikersnaam aangetroffen." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Gebruiker '%(nick)s' verwijderd" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "Kan Gast gebruiker niet verwijderen" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "SMTP-instellingen bewerken" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Kan laatste systeembeheerder niet verwijderen" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gelukt! Gmail account geverifieerd." -#: cps/admin.py:1542 cps/admin.py:1667 +#: 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 "Edit User %(nick)s" -msgstr "Gebruiker '%(nick)s' bewerken" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Gebruiker '%(nick)s' bijgewerkt" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Onbekende fout opgetreden. Probeer het later nog eens." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "SMTP-instellingen bewerken" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "Gmail Account succesvol geverifieerd" +msgid "Oops! Database Error: %(error)s." +msgstr "Database fout: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Gelieve eerst je e-mail adres configureren..." -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "E-mailserver-instellingen bijgewerkt" -#: cps/admin.py:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Bewerk instellingen van geplande taken" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "De starttijd van de taak is ongeldig" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "De duur van de taak is ongeldig" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Instellingen van geplande taken bijgewerkt" + +#: 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:1394 +msgid "Settings DB is not Writeable" +msgstr "Instellingen database is niet schrijfbaar." + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Gebruiker '%(nick)s' bewerken" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Logbestand lezer" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Update opvragen" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Update downloaden" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Update uitpakken" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Update toepassen" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databaseverbindingen zijn gesloten" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Bezig met stoppen van Calibre-Web" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Verbindingsfout" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Algemene fout" -#: cps/admin.py:1773 +#: 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:1774 +#: 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:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fout: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Gebruiker succesvol geïmporteerd" -#: cps/converter.py:30 -msgid "not installed" -msgstr "niet geïnstalleerd" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "Database niet gevonden, voer de juiste locatie in" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "Kan programma niet uitvoeren" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Kan niet schrijven naar database" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Aangepaste kolom Nr.%(column)d bestaat niet in de Calibre Database" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Geen" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Het boekformaat is verwijderd" +#: 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/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Het boek is verwijderd" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "E-mailserver-instellingen bijgewerkt" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Databaseconfiguratie" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Vul alle velden in!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "metagegevens bewerken" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "Het e-mailadres bevat geen geldige domeinnaam" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s is geen geldig nummer, sla het over" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Gebruiker toevoegen" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s is geen geldige taal" +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "Gebruiker '%(user)s' aangemaakt" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" -msgstr "" +#: cps/admin.py:1926 +#, fuzzy +msgid "Oops! An account already exists for this Email. or name." +msgstr "Bestaand account met dit e-mailadres of deze gebruikersnaam aangetroffen." -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, 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" +msgid "User '%(nick)s' deleted" +msgstr "Gebruiker '%(nick)s' verwijderd" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Het te uploaden bestand moet voorzien zijn van een extensie" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Kan Gast gebruiker niet verwijderen" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Kan de locatie '%(path)s' niet aanmaken (niet gemachtigd)." +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Kan laatste systeembeheerder niet verwijderen" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Kan %(file)s niet opslaan." +#: 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/editbooks.py:683 +#: cps/admin.py:2043 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Bestandsformaat %(ext)s toegevoegd aan %(book)s" +msgid "User '%(nick)s' updated" +msgstr "Gebruiker '%(nick)s' bijgewerkt" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: cps/converter.py:31 +msgid "not installed" +msgstr "niet geïnstalleerd" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Kan programma niet uitvoeren" + +#: 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: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 "Geen" + +#: 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: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:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "De metagegevens zijn bijgewerkt" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "Fout tijdens bijwerken van boek: {}" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Bestand %(file)s geüpload" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Bron- of doelformaat ontbreekt voor conversie" + +#: 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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Het boekformaat is verwijderd" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Het boek is verwijderd" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "U mist rechten om boeken te verwijderen" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "metagegevens bewerken" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Bestand %(file)s geüpload" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s is geen geldig nummer, sla het over" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Bron- of doelformaat ontbreekt voor conversie" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "Gebruiker mist rechten om extra bestandsformaten te uploaden" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, 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" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Kan de locatie '%(path)s' niet aanmaken (niet gemachtigd)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, 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" +msgid "Failed to store file %(file)s." +msgstr "Kan %(file)s niet opslaan." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Bestandsformaat %(ext)s toegevoegd aan %(book)s" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -619,187 +663,184 @@ msgstr "Het callback-domein is niet geverifieerd. Volg de stappen in de Google-o 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Versturen naar Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Test-e-mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Aan de slag met Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 converteren naar %(format)s en versturen naar Kindle" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "%(format)s versturen naar Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "%(book)s verzonden naar Kindle" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "Gelezen/ongelezen status kan niet aangepast worden: {}" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "Fout bij hernoemen bestand op bestandslocatie: {}" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Deze gebruikersnaam is al in gebruik" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Ongeldig E-Mail adres" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" -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:767 +#: 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:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Onjuist omslagformaat" -#: cps/helper.py:773 +#: 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:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Locatie aanmaken voor omslag mislukt" -#: cps/helper.py:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" -msgstr "" +msgstr "Ongeldig omslagbestand" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar executable niet gevonden" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Fout bij het uitvoeren van Unrar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Wachten" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Mislukt" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Gestart" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Voltooid" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Willekeurige boeken" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Onbekende status" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Voeg alle boeken toe aan de wachtrij voor het maken van een metagegevens backup" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo Instellen" @@ -808,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:1613 +#: 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 @@ -869,12 +910,13 @@ msgstr "Google OAuth fout, probeer het later nog eens." msgid "Google Oauth error: {}" msgstr "Google OAuth foutmelding: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} sterren" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -890,497 +932,619 @@ msgstr "Toegangssleutel is verlopen" msgid "Success! Please return to your device" msgstr "Gelukt! Ga terug naar je apparaat" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Boeken" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Recent toegevoegde boeken tonen" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Populaire boeken tonen" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Gedownloade boeken" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Ongelezen boeken tonen" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Willekeurige boeken" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Beoordelingen" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Bestandsformaten" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Gearchiveerde boeken" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Boekenlijst" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Zoeken" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Gepubliceerd na " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Gepubliceerd vóór " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Beoordeling <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Beoordeling >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Lees Status = %(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Geavanceerd zoeken" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Ongeldige boekenplank opgegeven" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Sorry, je mag geen boeken toevoegen aan boekenplank: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Dit boek maakt al deel uit van boekenplank: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Het boek is toegevoegd aan boekenplank: %(sname)s" -#: cps/shelf.py:126 +#: 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:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Deze boeken maken al deel uit van boekenplank: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "De boeken zijn toegevoegd aan boekenplank: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Kan boeken niet toevoegen aan boekenplank: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Het boek is verwijderd van boekenplank: %(sname)s" -#: cps/shelf.py:218 +#: 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:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Boekenplank maken" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Je bent niet gemachtigd deze boekenplank aan te passen" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Pas een boekenplank aan" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Fout bij verwijderen boekenplank!" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Het boek is verwijderd" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Volgorde van boekenplank veranderen: '%(name)s'" + +#: 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:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Boekenplank '%(title)s' aangemaakt" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Boekenplank '%(title)s' is aangepast" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Er is een fout opgetreden" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Boekenplank: '%(name)s'" + +#: 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:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Taken" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Wachten" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Mislukt" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Gestart" -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Het boek is verwijderd" +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Voltooid" -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Volgorde van boekenplank veranderen: '%(name)s'" +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Beëindigd" -#: cps/shelf.py:461 -#, python-format -msgid "Shelf: '%(name)s'" -msgstr "Boekenplank: '%(name)s'" +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Geannuleerd" -#: cps/shelf.py:465 -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:74 +msgid "Unknown Status" +msgstr "Onbekende status" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Onverwachte gegevens tijdens het uitlezen van de update-informatie" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Er is geen update beschikbaar." -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Er is een update beschikbaar. Klik op de knop hieronder om te updaten naar de nieuwste versie." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "De update-informatie kan niet worden opgehaald" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Klik op de onderstaande knop om de laatste stabiele versie te installeren." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Er is een update beschikbaar. Klik op de knop hieronder om te updaten naar versie: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Geen update-informatie beschikbaar" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Verkennen (willekeurige boeken)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Populaire boeken (meest gedownload)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Gedownloade boeken door %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Auteur: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Uitgever: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Reeks: %(serie)s" -#: cps/web.py:610 +#: 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:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Bestandsformaat: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categorie: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Taal: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Geavanceerd zoeken" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Zoeken" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Beoordelingen" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Alle bestandsformaten" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Taken" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Gepubliceerd na " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Gepubliceerd vóór " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Beoordeling <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Beoordeling >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Lees Status = %(status)s" - -#: cps/web.py:1425 -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/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Stel eerst SMTP-mail in..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, 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" +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:1531 +#: 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 "Fout opgetreden bij het versturen van dit boek: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Kan de LDAP authenticatie niet activeren" -#: cps/web.py:1621 -#, 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:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Inloggen mislukt: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Verkeerde gebruikersnaam of wachtwoord" -#: cps/web.py:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Calibre ebook-convert %(tool)s niet gevonden" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s formaat is niet gevonden op de schijf" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "E-Book converter mislukt met een onbekende foutmelding" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify-converteerder mislukt: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Omgezette bestand is niet gevonden of meer dan een bestand in map %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "E-boek-conversie mislukt: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre mislukt met foutmelding: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Overzetten" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Opnieuw verbinding aan het maken met Calibre database" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-mail" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "metagegevens bewerken" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "%{count}s omslagminiaturen gegenereerd" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "Omslag miniaturen" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "{0} serieminiaturen gegenereerd" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "Cache met omslagminiaturen aan het opschonen" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Uploaden" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Gebruikers" @@ -1393,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Kindle-e-mailadres" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Beheer" @@ -1410,13 +1575,8 @@ msgstr "Beheer" msgid "Password" msgstr "Wachtwoord" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Uploaden" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1430,7 +1590,7 @@ msgstr "Boeken lezen" msgid "Edit" msgstr "Bewerken" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1441,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 @@ -1471,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" @@ -1543,78 +1700,109 @@ msgstr "Bewerk basisconfiguratie" msgid "Edit UI Configuration" msgstr "Bewerk gebruikersinterface configuratie" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Geplande taken" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Starttijd" + +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +msgstr "Maximale duur" + +#: 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 "Genereer serie miniaturen" + +#: 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:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Genereer backupbestanden voor metagegevens" + +#: 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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Download foutopsporingspakket" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Logboeken bekijken" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Opnieuw verbinden met Calibre database" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Calibre-Web herstarten" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Calibre-Web stoppen" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Bijwerken" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Versie informatie" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versie" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Details" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Huidige versie" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Controleren op updates" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Update uitvoeren" -#: cps/templates/admin.html:210 +#: 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:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: 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:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Bezig met bijwerken, vernieuw de pagina niet" @@ -1626,39 +1814,39 @@ msgstr "via" msgid "In Library" msgstr "In bibliotheek" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Sorteren op datum, nieuwste boeken eerst" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Sorteren op datum, oudste boeken eerst" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Sorteren op alfabetische volgorde" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Sorteren op omgekeerde alfabetische volgorde" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Sorteren op publicatiedatum, nieuwste boeken eerst" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Sorteren op publicatiedatum, oudste boeken eerst" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "beperken" @@ -1666,165 +1854,166 @@ msgstr "beperken" msgid "More by" msgstr "Meer van" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Boek verwijderen" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Formaten verwijderen:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Boekformaat converteren:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Converteren van:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "kies een optie" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Converteren naar:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Boek converteren" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Boektitel" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Auteur" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Omschrijving" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identificatoren" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Identificatie type" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Identificatie waarde" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Verwijderen" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Identificator toevoegen" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Labels" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "Boekenreeks volgnummer" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Beoordeling" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Omslag-url (jpg) (de omslag wordt gedownload en opgeslagen in de database)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Omslag uploaden vanaf de harde schijf" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Publicatiedatum" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Uitgever" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Uploadformaat" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Boek inkijken na bewerking" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Metagegevens ophalen" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Opslaan" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Trefwoord" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Trefwoord zoeken " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Klik op de omslag om de metagegevens in het formulier te laden" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Bezig met laden..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Bron" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Zoekfout!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Geen resultaten gevonden! Gebruik een ander trefwoord." @@ -1914,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 "Archiv Status" -msgstr "" +msgid "Archive Status" +msgstr "Archiefstatus" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" @@ -1933,6 +2122,7 @@ msgid "Enter " msgstr "Identificatoren" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Weet je het zeker?" @@ -2007,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" @@ -2031,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" @@ -2054,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 @@ -2244,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" @@ -2256,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" @@ -2347,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lezen in webbrowser" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Luisteren in webbrowser" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Gepubliceerd" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Markeren als ongelezen" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Markeren als gelezen" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Gelezen" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Terughalen uit archief" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Toevoegen aan archief" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Gearchiveerd" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beschrijving:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2443,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:29 +#: 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" @@ -2472,188 +2713,196 @@ msgstr "Voer domeinnaam in" msgid "Denied Domains (Blacklist)" msgstr "Geweigerde domeinen voor registratie" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Kobo Sync Token" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Lijst" + +#: 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:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" -msgstr "" +msgstr "Sorteer oplopend volgens aantal downloads" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" -msgstr "" +msgstr "Sorteer aflopend volgens aantal downloads" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Auteurs sorteren op alfabetische volgorde" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Auteurs sorteren op omgekeerde alfabetische volgorde" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Sorteer oplopend volgens de serie index" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Startpagina" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Navigatie aanpassen" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Zoek in bibliotheek" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Account" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Afmelden" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Bezig met uploaden..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Fout" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Uploaden voltooid, bezig met verwerken..." -#: cps/templates/layout.html:76 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 "Instellingen" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Account" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Afmelden" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Deze pagina niet vernieuwen" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Verkennen" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informatie" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Vorige" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Boekgegevens" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Raster" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Gegevens opslaan" @@ -2662,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" @@ -2758,7 +3007,7 @@ msgstr "Bovenliggende map" msgid "Select" msgstr "Selecteer" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Oké" @@ -2772,128 +3021,162 @@ msgstr "Calibre-Web - e-boekcatalogus" msgid "epub Reader" msgstr "PDF lezer" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Licht" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Donker" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sepia" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Annuleren" + +#: 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:116 -msgid "Light" -msgstr "Licht" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Weergeven" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Donker" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Systeembeheer" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2902,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" @@ -2921,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 @@ -2940,15 +3223,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Genereer serie omslagminiaturen" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Geen resultaten gevonden" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Zoekterm:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Resultaten voor:" @@ -2960,64 +3247,72 @@ 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:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Deze boekenplank verwijderen" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Bewerk boekenplank eigenschappen" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Boeken handmatig rangschikken" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Schakel verandering van de volgorde uit" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Schakel verandering van de volgorde in" @@ -3062,8 +3357,8 @@ msgid "System Statistics" msgstr "Systeeminformatie" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Programmabibliotheek" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3089,9 +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 "Acties" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +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 "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" @@ -3123,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" @@ -3154,16 +3457,19 @@ 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 -msgid "Enter Kindle E-mail Address" -msgstr "Voer Kindle-e-mailadres in" +#, fuzzy +msgid "Enter eReader Email" +msgstr "Kindle-e-mailadres" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "Kindle-e-mail" +#, fuzzy +msgid "eReader Email" +msgstr "Test-e-mail" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3225,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 9fa13572..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 ce4898e6..7f0cd6bc 100644 --- a/cps/translations/pl/LC_MESSAGES/messages.po +++ b/cps/translations/pl/LC_MESSAGES/messages.po @@ -8,604 +8,648 @@ 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-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statystyki" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Ponowne połączenie zakończono sukcesem" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Nieznane polecenie" +#: cps/admin.py:173 +#, fuzzy +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:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Panel administratora" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Konfiguracja podstawowa" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Konfiguracja Interfejsu" -#: cps/admin.py:289 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:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Nie znaleziono użytkownika" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} użytkowników usuniętych pomyślnie" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Nieprawidłowo sformułowane żądanie" -#: cps/admin.py:436 cps/admin.py:1526 +#: 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:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gość nie może pełnić tej roli" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Nieprawidłowa rola" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gość nie może tego zobaczyć" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Nieprawidłowy widok" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Nie podano prawidłowej lokalizacji" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Nie podano obowiązującego języka książki" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Nie znaleziono parametru" -#: cps/admin.py:553 +#: cps/admin.py:571 #, fuzzy msgid "Invalid Read Column" msgstr "Nieprawidłowa kolumna odczytu" -#: cps/admin.py:559 +#: cps/admin.py:577 #, fuzzy msgid "Invalid Restricted Column" msgstr "Nieprawidłowa kolumna z ograniczeniami" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfiguracja Calibre-Web została zaktualizowana" -#: cps/admin.py:591 +#: 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:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Czy naprawdę chcesz usunąć tę domenę?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Czy naprawdę chcesz usunąć tego użytkownika?" -#: cps/admin.py:597 +#: 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:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -#, fuzzy -msgid "Tag not found" -msgstr "Nie znaleziono znacznika" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Nieprawidłowe działanie" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +#, fuzzy +msgid "Tag not found" +msgstr "Nie znaleziono znacznika" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Nieprawidłowe działanie" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Proszę wprowadzić konto usługi LDAP" -#: cps/admin.py:1154 +#: 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:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Filtr obiektów grupy LDAP ma niedopasowany nawias" -#: cps/admin.py:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Błąd bazy danych: %(error)s." - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "Lokalizacja bazy danych jest nieprawidłowa, wprowadź poprawną ścieżkę" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "Baza danych nie jest zapisywalna" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "Lokalizacja pliku klucza jest nieprawidłowa, wprowadź poprawną ścieżkę" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "Lokalizacja pliku certyfikatu jest nieprawidłowa, wprowadź poprawną ścieżkę" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Zaktualizowano ustawienia serwera poczty e-mail" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "Konfiguracja bazy danych" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Proszę wypełnić wszystkie pola!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-mail nie pochodzi z prawidłowej domeny" - -#: cps/admin.py:1416 cps/admin.py:1576 -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:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Użytkownik '%(user)s' został utworzony" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "Znaleziono istniejące konto dla tego adresu e-mail lub nazwy." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Użytkownik '%(nick)s' został usunięty" - -#: cps/admin.py:1465 cps/admin.py:1466 -#, fuzzy -msgid "Can't delete Guest User" -msgstr "Nie można usunąć użytkownika gościa" - -#: cps/admin.py:1469 -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:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Zmień ustawienia SMTP" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Edytuj użytkownika %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Użytkownik '%(nick)s' został zaktualizowany" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Wystąpił nieznany błąd. Spróbuj ponownie później." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Zmień ustawienia SMTP" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "Weryfikacja konta Gmail przebiegła pomyślnie" +msgid "Oops! Database Error: %(error)s." +msgstr "Błąd bazy danych: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Najpierw skonfiguruj swój adres e-mail..." -#: cps/admin.py:1637 -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:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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 "Wystąpił nieznany błąd. Spróbuj ponownie później." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Edytuj użytkownika %(nick)s" + +# ??? +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Przeglądanie dziennika" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Żądanie o pakiet aktualizacji" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Pobieranie pakietu aktualizacji" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Rozpakowywanie pakietu aktualizacji" # ??? -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Zastępowanie plików" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Połączenia z bazą danych zostały zakończone" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Zatrzymywanie serwera" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Błąd połączenia" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Błąd ogólny" -#: cps/admin.py:1773 +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Błąd: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Użytkownik pomyślnie zaimportowany" -#: cps/converter.py:30 -msgid "not installed" -msgstr "nie zainstalowane" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Brak uprawnienia do wykonywania pliku" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Baza danych nie jest zapisywalna" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Niestandardowa kolumna No.%(column)d nie istnieje w bazie calibre" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Brak" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Plik książki w wybranym formacie został usunięty" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Książka została usunięta" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "Zaktualizowano ustawienia serwera poczty e-mail" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Konfiguracja bazy danych" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Błąd otwierania e-booka. Plik nie istnieje lub jest niedostępny" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Proszę wypełnić wszystkie pola!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "edytuj metadane" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-mail nie pochodzi z prawidłowej domeny" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Dodaj nowego użytkownika" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s nie jest poprawną liczbą, pomijanie" +msgid "User '%(user)s' created" +msgstr "Użytkownik '%(user)s' został utworzony" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s nie jest prawidłowym językiem" +#: 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/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Użytkownik '%(nick)s' został usunięty" + +#: cps/admin.py:1959 +#, fuzzy +msgid "Can't delete Guest User" +msgstr "Nie można usunąć użytkownika gościa" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Użytkownik '%(nick)s' został zaktualizowany" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Plik do wysłania musi mieć rozszerzenie" +#: cps/converter.py:31 +msgid "not installed" +msgstr "nie zainstalowane" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Nie udało się utworzyć łącza %(path)s (Odmowa dostępu)." +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Brak uprawnienia do wykonywania pliku" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Nie można zapisać pliku %(file)s." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Format pliku %(ext)s dodany do %(book)s" +#: 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 "Brak" + +#: 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:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadane zostały pomyślnie zaktualizowane" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Wysłano plik %(file)s" + +#: 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: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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: 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:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Książka została usunięta" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "edytuj metadane" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Wysłano plik %(file)s" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s nie jest poprawną liczbą, pomijanie" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Brak formatu źródłowego lub docelowego do konwersji" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, 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" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Nie udało się utworzyć łącza %(path)s (Odmowa dostępu)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Podczas konwersji książki wystąpił błąd: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Nie można zapisać pliku %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Format pliku %(ext)s dodany do %(book)s" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -620,188 +664,186 @@ msgstr "Zwrotna domena nie jest zweryfikowana, proszę zweryfikowania domenę w 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Wyślij do Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Testowy e-mail" # ??? -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Zacznij korzystać z Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Wyślij %(format)s do Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Wyślij do Kindle" # ??? -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Nazwa użytkownika jest już zajęta" -#: cps/helper.py:669 -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:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Błąd przy pobieraniu okładki" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Błędny format okładki" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: 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:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Plik wykonywalny programu unrar nie znaleziony" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Błąd przy wykonywaniu unrar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Oczekiwanie" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Nieudane" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Rozpoczynanie" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Zakończone" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Odkrywaj" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Ststus nieznany" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Konfiguracja Kobo" @@ -811,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:1613 +#: 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 @@ -872,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:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Gwiazdek" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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ę" @@ -893,498 +936,619 @@ msgstr "Token wygasł" msgid "Success! Please return to your device" msgstr "Powodzenie! Wróć do swojego urządzenia" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Książki" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Pokaż menu ostatnio dodanych książek" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Najpopularniejsze" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Pokaż menu najpopularniejszych książek" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Pobrane książki" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Pokaż nieprzeczytane" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Odkrywaj" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Oceny" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Zarchiwizowane książki" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista książek" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Szukaj" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Opublikowane po " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Opublikowane przed " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Ocena <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Ocena >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Status przeczytania = %(status)s" + +#: 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:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Wyszukiwanie" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Podano niewłaściwą półkę" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Niestety, nie posiadasz uprawnień do dodania książki do półki: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Książka jest już dodana do półki: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Książka została dodana do półki: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Książki są już dodane do półki: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Książki zostały dodane do półki %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Nie można dodać książek do półki: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Książka została usunięta z półki: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Utwórz półkę" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Niestety nie możesz usunąć książki z tej półki %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Edytuj półkę" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Książka została usunięta" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Zmieniono kolejność półki: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Półka %(title)s została utworzona" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Półka %(title)s została zmieniona" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Wystąpił błąd" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Książka została usunięta" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Zmieniono kolejność półki: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Półka: „%(name)s”" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Zadania" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Oczekiwanie" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Nieudane" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Rozpoczynanie" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Zakończone" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Ststus nieznany" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Nieoczekiwane dane podczas odczytywania informacji o aktualizacji" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Brak dostępnej aktualizacji. Masz już zainstalowaną najnowszą wersję" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Dostępna jest nowa aktualizacja. Kliknij przycisk poniżej, aby zaktualizować do najnowszej wersji." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Nie można pobrać informacji o aktualizacji" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Kliknij przycisk poniżej, aby zaktualizować do najnowszej stabilnej wersji." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Dostępna jest nowa aktualizacja. Kliknij przycisk poniżej, aby zaktualizować do wersji: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Brak dostępnych informacji o wersji" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Odkrywaj (losowe książki)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Najpopularniejsze książki (najczęściej pobierane)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Książki pobrane przez %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Wydawca: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Cykl: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Ocena: %(rating)s gwiazdek" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Format pliku: %(format)s" -#: cps/web.py:663 -#, python-format -msgid "Category: %(name)s" -msgstr "Kategoria: %(name)s" - -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "Język: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Wyszukiwanie" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Szukaj" - -#: cps/templates/admin.html:16 cps/web.py:979 -msgid "Downloads" -msgstr "DLS" - -#: cps/web.py:1068 -msgid "Ratings list" -msgstr "Lista z ocenami" - -#: cps/web.py:1095 -msgid "File formats list" -msgstr "Lista formatów" - -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Zadania" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Opublikowane po " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Opublikowane przed " - -#: cps/web.py:1315 +#: cps/web.py:682 #, python-format -msgid "Rating <= %(rating)s" -msgstr "Ocena <= %(rating)s" +msgid "Category: %(name)s" +msgstr "Kategoria: %(name)s" -#: cps/web.py:1317 +#: cps/web.py:711 #, python-format -msgid "Rating >= %(rating)s" -msgstr "Ocena >= %(rating)s" +msgid "Language: %(name)s" +msgstr "Język: %(name)s" -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Status przeczytania = %(status)s" +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "DLS" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Lista z ocenami" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Lista formatów" -#: cps/web.py:1425 +#: cps/web.py:1233 #, fuzzy -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "Błąd podczas wyszukiwania kolumn niestandardowych, proszę zrestartować Calibre-Web" +msgid "Please configure the SMTP mail settings first..." +msgstr "Proszę najpierw skonfigurować ustawienia SMTP poczty e-mail..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, 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" +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:1531 +#: 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 "Wystąpił błąd podczas wysyłania tej książki: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Nie można aktywować uwierzytelniania LDAP" -#: cps/web.py:1621 -#, 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 "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" +msgstr "Fallback Login as: %(nickname)s, LDAP Server not reachable, or user not known" -#: cps/web.py:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Nie można zalogować: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: 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:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "Nie znaleziono narzędzia calibre %(tool)s do konwertowania" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "Nie znaleziono na dysku formatu %(format)s" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "Konwertowanie ebooka zakończyło się niepowodzeniem z nieznanego powodu" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify-converter spowodowało błąd: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Konwertowany plik nie został znaleziony, lub więcej niż jeden plik w folderze %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Konwertowanie nie powiodło się: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, fuzzy, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre nie powiodło się z błędem: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "edytuj metadane" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Wysyłanie" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Lista użytkowników" @@ -1397,15 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Adres e-mail dla wysyłania do Kindle" # ??? -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Panel administratora" @@ -1415,14 +1580,9 @@ msgstr "Panel administratora" msgid "Password" msgstr "Hasło" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Wysyłanie" - # ??? -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1437,7 +1597,7 @@ msgid "Edit" msgstr "Edycja" # ??? -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1448,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 @@ -1478,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 @@ -1549,78 +1706,109 @@ msgstr "Edytuj podstawową konfigurację" msgid "Edit UI Configuration" msgstr "Edytuj konfigurację interfejsu" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Zarządzanie" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Pobierz pakiet Debug" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Podgląd dziennika" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Połącz ponownie z bazą danych Calibre" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Uruchom ponownie Calibre Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Zatrzymaj Calibre Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Update (aktualizacja)" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Wersja" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Szczegóły" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Bieżąca wersja" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Sprawdź aktualizacje" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Wykonaj aktualizację" -#: cps/templates/admin.html:210 +#: 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:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Na pewno chcesz zatrzymać Calibre Web?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Aktualizowanie, proszę nie odświeżać strony" @@ -1632,39 +1820,39 @@ msgstr "przez" msgid "In Library" msgstr "W Bibliotece" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Sortuj książki według daty, najnowsze jako pierwsze" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Sortuj książki według daty, najstarsze jako pierwsze" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Sortuj tytuły w porządku alfabetycznym" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Sortuj tytuły w odwrotnym porządku alfabetycznym" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Sortuj według daty publikacji, najnowsze jako pierwsze" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Sortuj według daty publikacji, najstarsze jako pierwsze" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "zwiń" @@ -1672,166 +1860,167 @@ msgstr "zwiń" msgid "More by" msgstr "Więcej według" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Usuń książkę" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Usuń formaty:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Konwertuj format książki:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Konwertuj z:" # ??? -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "wybierz opcję" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Konwertuj na:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Konwertuj książkę" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Tytuł książki" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Opis" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identyfikatory" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Rodzaj identyfikatora" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Wartość identyfikatora" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "Usuń" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Dodaj identyfikator" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etykiety" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID cyklu" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Ocena" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Pobierz okładkę z linku (JPEG - obraz zostanie pobrany i zapisany w bazie)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Wyślij okładkę z dysku lokalnego" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Data publikacji" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Wydawca" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Wyślij format" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Po zapisaniu wyświetl szczegóły książki" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Uzyskaj metadane" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Zapisz" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Słowo kluczowe" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Szukaj słowa kluczowego " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Kliknij okładkę, aby załadować metadane do formularza" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Ładowanie..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Źródło" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Błąd wyszukiwania!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Nie znaleziono! Spróbuj użyć innego słowa kluczowego." @@ -1926,7 +2115,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1942,6 +2131,7 @@ msgid "Enter " msgstr "Identyfikatory" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Czy jesteś pewny?" @@ -2050,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 @@ -2066,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 @@ -2256,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" @@ -2268,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" @@ -2359,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Czytaj w przeglądarce" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Słuchaj w przeglądarce" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Data publikacji" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Oznacz jako nieprzeczytane" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Oznacz jako przeczytane" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Przeczytana" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Przywróć z archiwum" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Dodaj do archiwum" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Zarchiwizowane" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Opis:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2455,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:29 +#: 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óć" @@ -2484,192 +2725,200 @@ msgstr "Podaj nazwę domeny" msgid "Denied Domains (Blacklist)" msgstr "Domeny zabronione (czarna lista)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Token Kobo Sync" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Sortuj autorów w porządku alfabetycznym" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Posortuj autorów w odwrotnym porządku alfabetycznym" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Sortuj rosnąco według indeksu serii" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Główne menu" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Przełącz nawigację" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Przeszukaj bibliotekę" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Błąd" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Wysyłanie zakończone, przetwarzanie, proszę czekać…" -#: cps/templates/layout.html:76 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:78 -msgid "Account" -msgstr "Konto" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Wyloguj się" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Proszę nie odświeżać strony" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Przeglądaj" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informacje" # ??? -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Poprzedni" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Szczegóły książki" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Zapamiętaj mnie" @@ -2678,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”" @@ -2775,7 +3024,7 @@ msgstr "Główny katalog" msgid "Select" msgstr "Wybierz" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "OK" @@ -2788,128 +3037,162 @@ msgstr "Katalog e-booków Calibre-Web" msgid "epub Reader" msgstr "Czytnik PDF" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Jasny" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Ciemny" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Wróć" + +#: 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:116 -msgid "Light" -msgstr "Jasny" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Ciemny" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Panel administratora" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2918,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" @@ -2937,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 @@ -2956,15 +3239,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Brak wyników" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Wyszukiwano:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Wyniki dla:" @@ -2976,63 +3263,71 @@ 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:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Usuń tą półkę" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Edytuj właściwości półki" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Ręczne porządkowanie książek" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Wyłączenie Zlecenie zmiany" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Włącz polecenie zmiany" @@ -3077,8 +3372,8 @@ msgid "System Statistics" msgstr "Statystyki systemu" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Biblioteka programu" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3105,9 +3400,17 @@ 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 "" + +#: 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" @@ -3170,16 +3473,19 @@ 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 -msgid "Enter Kindle E-mail Address" -msgstr "Wprowadź adres e-mail Kindle" +#, fuzzy +msgid "Enter eReader Email" +msgstr "Adres e-mail dla wysyłania do Kindle" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "E-mail Kindle" +#, fuzzy +msgid "eReader Email" +msgstr "Testowy e-mail" #: cps/templates/user_table.html:137 #, fuzzy @@ -3241,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 b7052210..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 2431ffae..84a0a7f3 100644 --- a/cps/translations/pt_BR/LC_MESSAGES/messages.po +++ b/cps/translations/pt_BR/LC_MESSAGES/messages.po @@ -4,605 +4,637 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: br \n" -"Plural-Forms: nplurals=6; plural=(n==1 ? 0 : n%10==1 && n%100!=11 && n%100!=71 && n%100!=91 ? 1 : n%10==2 && n%100!=12 && n%100!=72 && n%100!=92 ? 2 : (n%10==3 || n%10==4 || n%10==9) && n%100!=13 && n%100!=14 && n%100!=19 && n%100!=73 && n%100!=74 && n%100!=79 && n%100!=93 && n%100!=94 && n%100!=99 ? 3 : n%1000000==0 ? 4 : 5)\n" +"Plural-Forms: nplurals=6; plural=(n==1 ? 0 : n%10==1 && n%100!=11 && n%100!=71 && n%100!=91 ? 1 : n%10==2 && n%100!=12 && n%100!=72 && n%100!=92 ? 2 : (n%10==3 || n%10==4 || n%10==9) && n%100!=13 && n%100!=14 && n%100!=19 && n%100!=73 && n%100!=74 && n%100!=79 && n%100!=93 && n%100!=94 && n%100!=99 ? 3 : n%1000000==0 ? 4 : 5);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" -msgstr "Estatística" +msgstr "Estatísticas" -#: cps/admin.py:141 -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:143 -msgid "Performing shutdown of server, please close window" -msgstr "Executando o desligamento do servidor, por favor, feche a janela" - #: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "Reconexão bem-sucedida" +#, fuzzy +msgid "Performing Server shutdown, please close window." +msgstr "Executando o desligamento do servidor, por favor feche a janela" -#: cps/admin.py:154 +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando desconhecido" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" -msgstr "Página de administração" +msgstr "Página de Administração" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuração Básica" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuração de UI" -#: cps/admin.py:289 cps/templates/admin.html:51 -#, fuzzy +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" -msgstr "Usuário Admin" +msgstr "Editar Usuários" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Usuário não encontrado" -#: cps/admin.py:374 -#, fuzzy +#: cps/admin.py:408 msgid "{} users deleted successfully" -msgstr "{} Usuário Importado com Sucesso" +msgstr "{} usuário(s) deletedos com sucesso" -#: cps/admin.py:397 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" +msgstr "Mostrar Tudo" -#: cps/admin.py:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" -msgstr "" +msgstr "Requisição Malformada" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" -msgstr "" +msgstr "Nome do Convidado não pode ser alterado" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" -msgstr "" +msgstr "Convidado não pode ter esta função" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" -msgstr "Nenhum usuário administrador restante, não pode remover a função de administrador" +msgstr "Nenhum usuário administrador restante, impossível remover a função de administrador" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" -msgstr "" +msgstr "Valor tem de ser Verdadeiro ou Falso" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" -msgstr "" +msgstr "Função Inválida" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" -msgstr "" +msgstr "Convidado não pode ter esta visão" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "" +msgstr "Visão Inválida" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" -msgstr "" +msgstr "O idioma do Convidado é detectado automaticamente e não pode ser alterado" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" -msgstr "" +msgstr "Nenhum Idioma Válido Fornecido" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" -msgstr "" +msgstr "Nenhum Idioma do Livro Válido Fornecido" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" -msgstr "" +msgstr "Parametro não encontrado" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" -msgstr "" +msgstr "Coluna Lido Inválida" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" -msgstr "" +msgstr "Coluna Restrito Inválida" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuração do Calibre-Web atualizada" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" -msgstr "Você realmente quer excluir o Kobo Token?" +msgstr "Você realmente quer apagar a Kobo Token?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" -msgstr "Você realmente quer excluir este domínio?" +msgstr "Você realmente quer apagar este domínio?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" -msgstr "Você realmente quer excluir este usuário?" +msgstr "Você realmente quer apagar este usuário?" -#: cps/admin.py:597 +#: 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:599 -#, fuzzy +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" -msgstr "Tem certeza que quer apagar essa estante?" +msgstr "Tem certeza que quer alterar o idioma do(s) usuário(s) selecionados?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" -msgstr "" +msgstr "Tem certeza que quer alterar os idiomas de livros visíveis par o usuário(s) selecionado(s)?" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" -msgstr "" +msgstr "Tem certeza que quer alterar a função selecionada para o(s) usuário(s) selecionado(s)?" -#: cps/admin.py:605 -#, fuzzy +#: 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 apagar essa estante?" +msgstr "Tem certeza que quer alterar as restriçõeo selecionada para o(s) usuário(s) selecionado(s)?" -#: cps/admin.py:607 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" -msgstr "" +msgstr "Tem certeza de que quer alterar as restrições de visibilidade selecionadas para os usuários selecionados?" -#: cps/admin.py:610 -#, fuzzy +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" -msgstr "Tem certeza que quer apagar essa estante?" +msgstr "Tem certeza de que quer alterar o comportamento de sincronização da estante para o usuário selecionado?" -#: cps/admin.py:612 -#, fuzzy +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" -msgstr "Tens a certeza que queres fechar?" - -#: cps/admin.py:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" -msgstr "" +msgstr "Tem certeza que queres alterar a localização da biblioteca Calibre?" -#: cps/admin.py:764 -msgid "Tag not found" -msgstr "" +#: 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:776 -msgid "Invalid Action" -msgstr "" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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 "Permita" +msgstr "Permitir" -#: cps/admin.py:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "" +msgstr "{} entradas de sincronização deletadas" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Tag 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 aplicativo da web" +msgstr "client_secrets.json Não Está Configurado para Aplicação Web" -#: cps/admin.py:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 -#, fuzzy +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" -msgstr "Por favor, digite um nome de usuário válido para redefinir a senha" +msgstr "Por favor, digite uma Conta de Serviço LDAP e Senha" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" -msgstr "" +msgstr "Por favor, digite uma Conta de Serviço LDAP" -#: cps/admin.py:1154 +#: 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:1156 +#: 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:1160 +#: 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:1162 +#: 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:1169 +#: 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:1171 +#: 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:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" -msgstr "LDAP CACertificate, Certificados ou chave de localização não é válida, Insira o caminho correto" - -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Erro de banco de dados: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "DB não é gravável" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "A localização do arquivo-chave não é válida, por favor insira o caminho correto" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "A localização do arquivo de certificação não é válida, digite o caminho correto" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Atualização das configurações do servidor de e-mail" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Configuração das Características" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Por favor, preencha todos os campos!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "O e-mail não é de um domínio válido" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Adicionar novo usuário" +msgstr "Localização de LDAP CACertificate, Certificados ou Key Inválida, Insira o Caminho Correto" -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Usuário '%(user)s' criado" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Encontrei uma conta existente para este endereço de e-mail ou apelido." +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Adicionar Novo Usuário" -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Usuário '%(nick)s' excluído" +#: 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:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Nenhum usuário administrador restante, não é possível excluir o usuário" - -#: cps/admin.py:1542 cps/admin.py:1667 +#: 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 "Edit User %(nick)s" -msgstr "Editar usuário %(nick)s" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Usuário '%(nick)s' atualizado" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente mais tarde." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Editar configurações do servidor de e-mail" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "" +msgid "Oops! Database Error: %(error)s." +msgstr "Erro de banco de dados: %(error)s." -#: cps/admin.py:1630 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" -msgstr "" +msgstr "E-mail de teste enfileirado para envio para %(email)s, verifique o resultado em Tarefas" -#: cps/admin.py:1633 +#: 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:1635 +#: 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:1637 -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:1679 +#: 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 "Configurações de tarefas agendadas atualizadas" + +#: 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 "Settings DB não é gravável" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" -msgstr "Senha para redefinição do usuário %(user)s" +msgid "Edit User %(nick)s" +msgstr "Editar Usuário %(nick)s" -#: cps/admin.py:1685 cps/web.py:1522 -msgid "Please configure the SMTP mail settings first..." +#: 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:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Por favor, configure primeiro as configurações de correio SMTP..." -#: cps/admin.py:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" -msgstr "visualizador de arquivo de registro" +msgstr "Visualizador do Log" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Solicitação de pacote de atualização" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" -msgstr "Download do pacote de atualização" +msgstr "Baixando pacote de atualização" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" -msgstr "Descompactação de pacote de atualização" +msgstr "Descompactando pacote de atualização" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" -msgstr "Substituição de arquivos" +msgstr "Substituindo arquivos" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" -msgstr "As ligações à base de dados estão fechadas" +msgstr "As conexões à base de dados estão fechadas" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" -msgstr "Parar servidor" +msgstr "Parando servidor" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Erro de conexão" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Erro geral" -#: cps/admin.py:1773 -#, fuzzy +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" -msgstr "" +msgstr "Arquivos não puderam ser substituídos durante a atualização" -#: cps/admin.py:1798 -#, fuzzy +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" -msgstr "Falha na criação no mínimo de um usuário LDAP" +msgstr "Falha ao extrair pelo menos um usuário LDAP" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" -msgstr "Falha na criação no mínimo de um usuário LDAP" +msgstr "Falha ao criar pelo menos um usuário LDAP" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Erro: %(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" -msgstr "Erro: Nenhum usuário retornado em resposta do servidor LDAP" +msgstr "Erro: Nenhum usuário retornado na resposta do servidor LDAP" -#: cps/admin.py:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Usuário Importado com Sucesso" -#: cps/converter.py:30 -msgid "not installed" -msgstr "não instalado" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Faltam as permissões de execução" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "DB não é gravável" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "A coluna personalizada No.%(column)d não existe no banco de dados do calibre" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Nenhum" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Formato do Livro Eliminado com Sucesso" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Livro Eliminado com Sucesso" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Configurações do Banco de Dados Atualizada" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Configuração do Banco de Dados" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Oops! O título do livro seleccionado não está disponível. O arquivo não existe ou não é acessível" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Por favor, preencha todos os campos!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "editar metadados" +#: 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:1909 +msgid "Add new user" +msgstr "Adicionar novo usuário" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "" +msgid "User '%(user)s' created" +msgstr "Usuário '%(user)s' criado" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s não é um idioma válido" +#: 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/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Usuário '%(nick)s' excluído" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Impossível excluir Convidado" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Usuário '%(nick)s' atualizado" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "O arquivo a ser carregado deve ter uma extensão" +#: cps/converter.py:31 +msgid "not installed" +msgstr "não instalado" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Falha ao criar o caminho %(path)s (Permission denied)." +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Faltam as permissões de execução" -#: cps/editbooks.py:660 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Failed to store file %(file)s." -msgstr "Falha ao armazenar o arquivo %(file)s." +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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Formato de arquivo %(ext)s adicionado a %(book)s" +#: 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 arquivo não existe ou não é acessível" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "Usuário não tem permissão para fazer upload da capa" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" -msgstr "Os identificadores não são sensíveis a maiúsculas ou minúsculas, mas sim a maiúsculas e minúsculas" +msgstr "Os identificadores não diferenciam maiúsculas de minúsculas, substituindo o identificador antigo" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadados atualizados com sucesso" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "Erro ao editar o livro: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Arquivo %(file)s enviado" + +#: 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: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: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:951 +#: 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 mudar antes de carregar novo: " +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 arquivo '%(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 arquivo a ser carregado deve ter uma extensão" -#: cps/editbooks.py:1041 +#: 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:1061 +#: 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" +msgstr "Falha ao mover arquivo de capa %(file)s: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Formato do Livro Apagado com Sucesso" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Livro Apagado com Sucesso" + +#: 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:1117 +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "editar metadados" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Arquivo %(file)s enviado" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s não é um número válido, ignorando" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Falta o formato de origem ou destino para a conversão" +#: 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:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Livro enfileirado com sucesso para conversão em %(book_format)s" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Falha ao criar o caminho %(path)s (Permission denied)." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Ocorreu um erro ao converter este livro: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Falha ao armazenar o arquivo %(file)s." + +#: 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" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -610,194 +642,189 @@ msgstr "Configuração do Google Drive não concluída, tente desativar e ativar #: 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 é verificado, por favor siga os passos para verificar o domínio no console do desenvolvedor do google" +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: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" +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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" -msgstr "Enviar para Kindle" +#: 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:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "E-mail de teste" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Comece a usar o calibre-web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" -msgstr "Converta %(orig)s em %(format)s e envie para o Kindle" +#: 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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" -msgstr "Envie %(format)s para o Kindle" +#: 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:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" -msgstr "Enviar para Kindle" +msgid "%(book)s send to eReader" +msgstr "%(book)s enviado para E-Reader" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "Status Lido não pode ser alterado: {}" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 -#, fuzzy, python-format +#: 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, caminho do livro inválido: %(path)s" +msgstr "Excluindo livro %(id)s somente do banco de dados, caminho do livro inválido: %(path)s" -#: cps/helper.py:458 -#, fuzzy, python-format +#: cps/helper.py:447 +#, python-format msgid "Rename author 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" +msgstr "Renomear autor de: '%(src)s' para '%(dest)s' falhou com o erro: %(error)s" -#: cps/helper.py:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "Erro ao renomear arquivo no caminho: {}" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Encontrado 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Este nome de usuário já está registrado" -#: cps/helper.py:669 -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:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: 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:862 msgid "Error Downloading Cover" msgstr "Erro ao Baixar a capa" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Erro de Formato da Capa" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" -msgstr "" +msgstr "Você não tem permissão para acessar localhost ou a rede local para uploads de capa" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Falha em criar caminho para a capa" -#: cps/helper.py:799 +#: 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:810 +#: 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 arquivos de capa" +msgstr "Apenas arquivos jpg/jpeg/png/webp/bmp são suportados como arquivos de capa" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" -msgstr "" +msgstr "Conteúdo do arquivo de capa inválido" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" -msgstr "Unrar arquivo binário não encontrado" +msgstr "Binário Unrar não encontrado" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Erro excecutando UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Aguardando" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Falha" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Iniciado em" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Concluído" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Capa" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Status Desconhecido" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 -#, fuzzy +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuração Kobo" @@ -806,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:1613 +#: 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 @@ -818,7 +845,7 @@ msgstr "Link para %(oauth)s bem-sucedido" #: cps/oauth_bb.py:155 msgid "Login failed, No User Linked With OAuth Account" -msgstr "Login falhou, nenhum utilizador ligado a uma conta OAuth" +msgstr "Login falhou, nenhum usuário ligado a uma conta OAuth" #: cps/oauth_bb.py:197 #, python-format @@ -849,30 +876,31 @@ msgstr "Falha no login com o Google." #: cps/oauth_bb.py:285 msgid "Failed to fetch user info from Google." -msgstr "Falha em ir buscar informações de usuário ao Google." +msgstr "Falha na busca de informações de usuário no Google." #: cps/oauth_bb.py:332 msgid "GitHub Oauth error, please retry later." -msgstr "Erro de GitHub Oauth, por favor tente novamente mais tarde." +msgstr "Erro no Oauth do GitHub, tente novamente mais tarde." #: cps/oauth_bb.py:335 msgid "GitHub Oauth error: {}" -msgstr "" +msgstr "Erro no Oauth do GitHub: {}" #: cps/oauth_bb.py:356 msgid "Google Oauth error, please retry later." -msgstr "Erro no Google Oauth, por favor tente novamente mais tarde." +msgstr "Erro no Google Oauth, tente novamente mais tarde." #: cps/oauth_bb.py:359 msgid "Google Oauth error: {}" -msgstr "" +msgstr "Erro no Oauth do Google: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" -msgstr "" +msgstr "{} Estrelas" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -888,497 +916,615 @@ msgstr "O Token expirou" msgid "Success! Please return to your device" msgstr "Sucesso! Por favor, volte ao seu aparelho" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Livros" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Mostrar livros recentes" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Mostrar Livros Quentes" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" -msgstr "Livros descarregados" +msgstr "Livros Baixados" -#: cps/render_template.py:50 cps/render_template.py:55 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" -msgstr "Mostrar Livros Descarregados" +msgstr "Mostrar Livros Baixados" -#: cps/render_template.py:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" -msgstr "Mostrar os melhores livros avaliados" +msgstr "Mostrar Livros Mais Bem Avaliados" -#: cps/render_template.py:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" -msgstr "Mostrar não lido" +msgstr "Mostrar Não Lidos" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Descubra" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 cps/templates/user_table.html:157 -msgid "Show series selection" -msgstr "Mostrar selecçã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:77 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:79 cps/templates/user_table.html:160 -msgid "Show author selection" -msgstr "Mostrar selecçã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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" -msgstr "Editores" +msgstr "Editoras" -#: cps/render_template.py:83 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "Mostrar selecção de editores" +#: 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" -msgstr "Classificações" +msgstr "Avaliações" -#: cps/render_template.py:90 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "Mostrar selecção de classificaçõ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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Livros Arquivados" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista de Livros" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Avaliação <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Avaliação >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Status 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, 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:73 -#, fuzzy +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" -msgstr "Desculpe, você não tem permissão para adicionar um livro à estante: %(shelfname)s" +msgstr "Desculpe, você não tem permissão para adicionar um livro a esta estante" -#: cps/shelf.py:82 +#: 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:107 +#: 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:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" -msgstr "" +msgstr "Você não tem permissão para adicionar um livro à estante" -#: cps/shelf.py:144 +#: 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:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Livros foram adicionados à estante: %(sname)s" -#: cps/shelf.py:163 +#: 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:209 +#: 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:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" -msgstr "" +msgstr "Desculpe, você não tem permissão para remover um livro desta estante" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" -msgstr "Crie uma estante" +msgstr "Crie uma Estante" -#: cps/shelf.py:236 -#, fuzzy +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" -msgstr "Desculpe, você não tem permissão para remover um livro desta estante: %(sname)s" +msgstr "Desculpe, você não tem permissão para editar esta estante" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Editar uma estante" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Erro apagando Estante" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Estante Apagada 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 "" +msgstr "Desculpe, você não tem permissão para criar uma estante pública" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Estante %(title)s criada" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Estante %(title)s alterada" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Houve um erro" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Livro Eliminado com Sucesso" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Alterar ordem da Estante: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Estante: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: 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 "Falha" + +#: 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 "Status 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:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Não há atualização disponível. Você já tem a última versão instalada" -#: cps/updater.py:451 +#: 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:469 +#: cps/updater.py:474 msgid "Could not fetch update information" -msgstr "Não consegui obter informações actualizadas" +msgstr "Não foi possível buscar as informações de atualização" -#: cps/updater.py:479 +#: 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:488 cps/updater.py:502 cps/updater.py:513 +#: 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:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Não há informações de lançamento disponíveis" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Descobrir (Livros Aleatórios)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" -msgstr "Hot Books (Os Mais Descarregados)" +msgstr "Livros Quentess (Mais Baixados)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Livros baixados por %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" -msgstr "Editor: %(name)s" +msgstr "Editora: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Série: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Avaliação: Nenhuma" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Avaliação: %(rating)s estrelas" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato do arquivo: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoria: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Idioma: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Pesquisa Avançada" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Pesquisa" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" -msgstr "Lista de classificações" +msgstr "Lista de Avaliações" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista de formatos de arquivo" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Tarefas" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Publicado depois de " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Publicado antes de " +#: 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:1315 +#: cps/web.py:1240 #, python-format -msgid "Rating <= %(rating)s" -msgstr "Avaliação <= %(rating)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Livro enfileirado com sucesso para envio para %(eReadermail)s" -#: cps/web.py:1317 +#: cps/web.py:1243 #, python-format -msgid "Rating >= %(rating)s" -msgstr "Avaliação >= %(rating)s" +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Ops! Ocorreu um erro ao enviar este livro: %(res)s" -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Status de leitura = %(status)s" +#: 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:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/web.py:1527 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Livro enfileirado com sucesso para envio para %(kindlemail)s" - -#: cps/web.py:1531 -#, python-format -msgid "Oops! There was an error sending this book: %(res)s" -msgstr "Ups! Ocorreu um erro ao enviar este livro: %(res)s" - -#: cps/web.py:1533 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." -msgstr "Por favor, atualize seu perfil com um endereço de e-mail válido para Kindle." - -#: cps/web.py:1550 -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/templates/layout.html:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: 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:1621 -#, 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:1627 -#, 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:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" -msgstr "Nome de usuário ou senha incorretos" +msgstr "Nome de Usuário ou Senha incorretos" -#: cps/web.py:1638 +#: 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" +msgstr "Nova Senha foi enviada para seu endereço de e-mail" + +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" -msgstr "Perfil de %(name)s's" +msgid "%(name)s's Profile" +msgstr "Perfil de %(name)s" -#: cps/web.py:1733 -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 "" +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:154 +#: 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:187 +#: 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:191 +#: 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:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" -msgstr "O conversor de Kepubify falhou: %(error)s" +msgstr "Kepubify-converter falhou: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Arquivo convertido não encontrado ou mais de um arquivo na pasta %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" -msgstr "Conversor de ebook falhou: %(error)s" +msgstr "Ebook-converter falhou: %(error)s" -#: cps/tasks/convert.py:269 +#: 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 "Reconectando banco de dados Calibre" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-mail" + +#: 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 "Gerado %(count)s miniaturas de capa" + +#: 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:289 +msgid "Generated {0} series thumbnails" +msgstr "Gerado {0} miniaturas de série" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Upload" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Usuários" @@ -1391,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 Kindle E-mail Address" -msgstr "Enviar para o endereço de e-mail do Kindle" +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:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1408,13 +1554,8 @@ msgstr "Admin" msgid "Password" msgstr "Senha" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Upload" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1428,36 +1569,32 @@ msgstr "Ver Livros" msgid "Edit" msgstr "Editar" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 "Eliminar" +msgstr "Apagar" #: cps/templates/admin.html:26 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 msgid "SMTP Hostname" -msgstr "SMTP Nome do anfitrião" +msgstr "SMTP Hostname" #: cps/templates/admin.html:71 cps/templates/email_edit.html:35 msgid "SMTP Port" -msgstr "Porto SMTP" +msgstr "Porta SMTP" #: cps/templates/admin.html:75 cps/templates/email_edit.html:39 msgid "Encryption" @@ -1469,16 +1606,17 @@ 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" -msgstr "" +#, fuzzy +msgid "Email Service" +msgstr "Serviço de E-Mail" #: cps/templates/admin.html:91 msgid "Gmail via Oauth2" -msgstr "" +msgstr "Gmail via Oauth2" #: cps/templates/admin.html:106 msgid "Configuration" @@ -1486,19 +1624,19 @@ msgstr "Configuração" #: cps/templates/admin.html:109 msgid "Calibre Database Directory" -msgstr "Diretório do Banco de Dados de Calibres" +msgstr "Diretório do Banco de Dados Calibre" #: cps/templates/admin.html:113 cps/templates/config_edit.html:68 msgid "Log Level" -msgstr "Nível de registo" +msgstr "Nível de Log" #: cps/templates/admin.html:117 msgid "Port" -msgstr "Porto" +msgstr "Porta" #: cps/templates/admin.html:122 msgid "External Port" -msgstr "Porto externo" +msgstr "Porta externa" #: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 msgid "Books per Page" @@ -1522,99 +1660,129 @@ msgstr "Login remoto Magic Link" #: cps/templates/admin.html:149 msgid "Reverse Proxy Login" -msgstr "Login de Proxy Reversa" +msgstr "Login 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 -#, fuzzy msgid "Edit Calibre Database Configuration" -msgstr "Editar Configuração Básica" +msgstr "Editar Configuração do Banco de Dados do Calibre" #: cps/templates/admin.html:160 msgid "Edit Basic Configuration" -msgstr "Editar Configuração Básica" +msgstr "Editar Configurações Básicas" #: cps/templates/admin.html:161 msgid "Edit UI Configuration" -msgstr "Editar configuração da IU" +msgstr "Editar Configuração de UI" + +#: 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 em que as tarefas começam a ser executadas" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +msgstr "Duração máxima das tarefas" + +#: 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/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Reconectar à Biblioteca do Calibre" + +#: 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:203 msgid "Administration" msgstr "Administração" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" -msgstr "Download do Pacote de Depuração" +msgstr "Baixar Pacote de Depuração" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Ver Logs" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Reconectar base de dados de calibração" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" -msgstr "Reinicie" +msgstr "Reiniciar" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" -msgstr "Encerramento" +msgstr "Desligar" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Atualização" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Informação da Versão" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versão" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detalhes" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versão atual" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Verificar Atualizações" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Realizar Atualizações" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" -msgstr "Tem a certeza que quer recomeçar?" +msgstr "Tem a certeza que quer reiniciar?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" -msgstr "Tens a certeza que queres fechar?" +msgstr "Tem certeza que quer encerrar?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" -msgstr "Atualizando, por favor, não recarregue esta página" +msgstr "Atualizando, por favor não recarregue esta página" #: cps/templates/author.html:15 msgid "via" @@ -1624,39 +1792,39 @@ msgstr "via" msgid "In Library" msgstr "Na Biblioteca" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Classificar de acordo com a data do livro, o mais recente primeiro" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Classificar de acordo com a data do livro, o mais antigo primeiro" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Classificar título em ordem alfabética" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Classificar título em ordem alfabética inversa" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Classificar de acordo com a data de publicação, o mais novo primeiro" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Classificar de acordo com a data de publicação, primeiro mais antigo" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "reduzir" @@ -1664,165 +1832,165 @@ msgstr "reduzir" msgid "More by" msgstr "Mais por" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" -msgstr "Eliminar Livro" +msgstr "Apagar Livro" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" -msgstr "Eliminar formatos:" +msgstr "Apagar formatos:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" -msgstr "Converta o formato do livro:" +msgstr "Converter formato do livro:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" -msgstr "Converte de:" +msgstr "Converter de:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "selecione uma opção" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" -msgstr "Converte para:" +msgstr "Converter para:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Converter livro" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: 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:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identificadores" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Tipo de identificador" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Valor do Identificador" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: 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:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Adicionar Identificador" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" -msgstr "Etiquetas" +msgstr "Tags" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "Identificação da série" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" -msgstr "Classificação" +msgstr "Avaliação" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Buscar capa na URL (JPEG - Imagem será baixada e armazenada na base de dados)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" -msgstr "Upload de capa do disco local" +msgstr "Upload de Capa do Disco Local" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Data de Publicação" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Formato de upload" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" -msgstr "Ver Livro ao salvar" +msgstr "Ver Livro ao Salvar" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Buscar Metadados" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Salvar" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Palavra-chave" -#: cps/templates/book_edit.html:233 -#, fuzzy +#: cps/templates/book_edit.html:234 msgid "Search keyword" -msgstr " Pesquisar palavra-chave " +msgstr "Pesquisar palavra-chave" -#: cps/templates/book_edit.html:239 +#: 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:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." -msgstr "A carregar..." +msgstr "Carregando..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Fonte" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Erro de busca!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Nenhum resultado(s) encontrado(s)! Por favor, tente outra palavra-chave." @@ -1834,7 +2002,7 @@ msgstr "Este campo é obrigatório" #: cps/templates/book_table.html:37 msgid "Merge selected books" -msgstr "Fundir livros selecionados" +msgstr "Mesclar livros selecionados" #: cps/templates/book_table.html:38 cps/templates/user_table.html:124 msgid "Remove Selections" @@ -1842,19 +2010,19 @@ msgstr "Remover Seleções" #: cps/templates/book_table.html:41 msgid "Exchange author and title" -msgstr "" +msgstr "Trocar autor e título" #: cps/templates/book_table.html:47 msgid "Update Title Sort automatically" -msgstr "Atualizar a Classificação de Título automaticamente" +msgstr "Atualizar Ordenação de Título automaticamente" #: cps/templates/book_table.html:51 msgid "Update Author Sort automatically" -msgstr "Atualizar a Classificação do Autor automaticamente" +msgstr "Atualizar Ordenação de Autor automaticamente" #: cps/templates/book_table.html:63 cps/templates/book_table.html:69 msgid "Enter Title" -msgstr "Digite o título" +msgstr "Digite o Título" #: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 #: cps/templates/shelf_edit.html:8 @@ -1863,19 +2031,19 @@ msgstr "Título" #: cps/templates/book_table.html:64 msgid "Enter Title Sort" -msgstr "Digite o título Sort" +msgstr "Digite a ordenação do título" #: cps/templates/book_table.html:64 msgid "Title Sort" -msgstr "Título Ordenar" +msgstr "Ordenação de Título" #: cps/templates/book_table.html:65 msgid "Enter Author Sort" -msgstr "Digite Author Sort" +msgstr "Digite a Ordenação de Author" #: cps/templates/book_table.html:65 msgid "Author Sort" -msgstr "Ordenar Autor" +msgstr "Ordenação de Autor" #: cps/templates/book_table.html:66 msgid "Enter Authors" @@ -1883,68 +2051,67 @@ msgstr "Entrar Autores" #: cps/templates/book_table.html:67 msgid "Enter Categories" -msgstr "Entrar nas categorias" +msgstr "Entrar Categorias" #: cps/templates/book_table.html:68 msgid "Enter Series" -msgstr "Entrar na série" +msgstr "Entrar Série" #: cps/templates/book_table.html:69 msgid "Series Index" -msgstr "Índice da série" +msgstr "Índice da Série" #: cps/templates/book_table.html:70 msgid "Enter Languages" -msgstr "Entrar idiomas" +msgstr "Entrar Idiomas" #: cps/templates/book_table.html:71 msgid "Publishing Date" -msgstr "Data de publicação" +msgstr "Data de Publicação" #: cps/templates/book_table.html:72 msgid "Enter Publishers" -msgstr "Entrar Editores" +msgstr "Entrar Editoras" #: cps/templates/book_table.html:73 -#, fuzzy msgid "Enter comments" -msgstr "Digite o nome do domínio" +msgstr "Entrar Comentários" #: cps/templates/book_table.html:73 msgid "Comments" -msgstr "" +msgstr "Comentários" #: cps/templates/book_table.html:75 -msgid "Archiv Status" -msgstr "" +msgid "Archive Status" +msgstr "Status Arquivado" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" -msgstr "Ler Estado" +msgstr "Status Lido" #: 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 -#, fuzzy msgid "Enter " -msgstr "Identificadores" +msgstr "Entrar " #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" -msgstr "Tens mesmo a certeza?" +msgstr "Você realmente tem certeza?" #: cps/templates/book_table.html:117 msgid "Books with Title will be merged from:" -msgstr "Os livros com título serão fundidos a partir de:" +msgstr "Livros com Título serão mesclados de:" #: cps/templates/book_table.html:121 msgid "Into Book with Title:" -msgstr "Into Book with Title:" +msgstr "Em livro com título:" #: cps/templates/book_table.html:126 msgid "Merge" -msgstr "Fundir" +msgstr "Mesclar" #: cps/templates/config_db.html:12 msgid "Location of Calibre Database" @@ -1952,7 +2119,7 @@ msgstr "Localização da Base de Dados Calibre" #: cps/templates/config_db.html:22 msgid "Use Google Drive?" -msgstr "Use o Google Drive?" +msgstr "User Google Drive?" #: cps/templates/config_db.html:27 msgid "Authenticate Google Drive" @@ -1960,7 +2127,7 @@ msgstr "Autenticar o Google Drive" #: cps/templates/config_db.html:32 msgid "Google Drive Calibre folder" -msgstr "Pasta Google Drive Calibre" +msgstr "Pasta Calibre no Google Drive" #: cps/templates/config_db.html:40 msgid "Metadata Watch Channel ID" @@ -1971,9 +2138,8 @@ msgid "Revoke" msgstr "Revogar" #: cps/templates/config_db.html:68 -#, fuzzy msgid "New db location is invalid, please enter valid path" -msgstr "A localização do banco de dados não é válida, digite o caminho correto" +msgstr "Novo local do banco de dados inválido, insira um caminho válido" #: cps/templates/config_edit.html:18 msgid "Server Configuration" @@ -1981,19 +2147,19 @@ msgstr "Configuração do Servidor" #: cps/templates/config_edit.html:25 msgid "Server Port" -msgstr "Porta do servidor" +msgstr "Porta do Servidor" #: cps/templates/config_edit.html:28 msgid "SSL certfile location (leave it empty for non-SSL Servers)" -msgstr "SSL certfile location (deixe-o vazio para Servidores não-SSL)" +msgstr "Localização do certfile SSL (deixe vazio para Servidores não-SSL)" #: cps/templates/config_edit.html:35 msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" -msgstr "SSL Keyfile location (deixe-o vazio para servidores não-SSL)" +msgstr "Localização do Keyfile SSL (deixe vazio para Servidores não-SSL)" #: cps/templates/config_edit.html:43 msgid "Update Channel" -msgstr "Canal de atualização" +msgstr "Canal de Atualização" #: cps/templates/config_edit.html:45 msgid "Stable" @@ -2001,15 +2167,15 @@ msgstr "Estável" #: cps/templates/config_edit.html:46 msgid "Nightly" -msgstr "Nocturno" +msgstr "Nightly" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "" +msgstr "Hosts confiáveis (Separado por vírgula)" #: cps/templates/config_edit.html:61 msgid "Logfile Configuration" -msgstr "Configuração do ficheiro de registo" +msgstr "Configuração do Arquivo de Log" #: cps/templates/config_edit.html:77 msgid "Location and name of logfile (calibre-web.log for no entry)" @@ -2025,23 +2191,23 @@ msgstr "Localização e nome do arquivo de log de acesso (access.log para nenhum #: cps/templates/config_edit.html:96 msgid "Feature Configuration" -msgstr "Configuração das Características" +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 "" +msgstr "Converta caracteres não ingleses em título e autor enquanto salva em disco" #: cps/templates/config_edit.html:108 msgid "Enable Uploads" msgstr "Habilitar Uploads" #: 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 "(Por favor, certifique-se de que os usuários também tenham direitos de upload)" #: cps/templates/config_edit.html:112 msgid "Allowed Upload Fileformats" -msgstr "Upload de formatos de arquivo permitidos" +msgstr "Formatos de arquivo de upload permitidos" #: cps/templates/config_edit.html:118 msgid "Enable Anonymous Browsing" @@ -2052,28 +2218,28 @@ 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 msgid "Enable Magic Link Remote Login" -msgstr "Habilitar login remoto do Magic Link" +msgstr "Habilitar Login Remoto do Magic Link" #: cps/templates/config_edit.html:137 msgid "Enable Kobo sync" -msgstr "Activar a sincronização de Kobo" +msgstr "Ativar Kobo sync" #: cps/templates/config_edit.html:142 msgid "Proxy unknown requests to Kobo Store" -msgstr "Proxy de pedidos desconhecidos para a loja Kobo" +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 de porta encaminhadas)" +msgstr "Porta externa do servidor (para chamadas API encaminhadas)" #: cps/templates/config_edit.html:153 msgid "Use Goodreads" -msgstr "Use Goodreads" +msgstr "Usar Goodreads" #: cps/templates/config_edit.html:154 msgid "Create an API Key" @@ -2081,15 +2247,15 @@ msgstr "Criar uma chave API" #: cps/templates/config_edit.html:158 msgid "Goodreads API Key" -msgstr "Goodreads Chave API" +msgstr "Chave API Goodreads" #: cps/templates/config_edit.html:162 msgid "Goodreads API Secret" -msgstr "Goodreads API Secreto" +msgstr "Senha API Goodreads" #: cps/templates/config_edit.html:169 msgid "Allow Reverse Proxy Authentication" -msgstr "Permitir a Autenticação por Proxy Reversa" +msgstr "Permitir a Autenticação por Proxy Reverso" #: cps/templates/config_edit.html:180 msgid "Login type" @@ -2097,15 +2263,15 @@ msgstr "Tipo de Login" #: cps/templates/config_edit.html:182 msgid "Use Standard Authentication" -msgstr "Usar autenticação padrão" +msgstr "Usar Autenticação padrão" #: cps/templates/config_edit.html:184 msgid "Use LDAP Authentication" -msgstr "Usar autenticação LDAP" +msgstr "Usar Autenticação LDAP" #: cps/templates/config_edit.html:187 msgid "Use OAuth" -msgstr "Use OAuth" +msgstr "Usar OAuth" #: cps/templates/config_edit.html:194 msgid "LDAP Server Host Name or IP Address" @@ -2129,15 +2295,15 @@ msgstr "SSL" #: cps/templates/config_edit.html:210 msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP CACertificate Path (Somente necessário para Autenticação de Certificado de Cliente)" +msgstr "Caminho do CACertificate LDAP (Necessário apenas para autenticação de certificado de cliente)" #: cps/templates/config_edit.html:217 msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP Certificate Path (Somente necessário para Autenticação de Certificado de Cliente)" +msgstr "Caminho do Certificado LDAP (Necessário apenas para autenticação de certificado de cliente)" #: cps/templates/config_edit.html:224 msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP Keyfile Path (Somente necessário para Autenticação de Certificado de Cliente)" +msgstr "Caminho do Keyfile LDAP (Necessário apenas para autenticação de certificado de cliente)" #: cps/templates/config_edit.html:233 msgid "LDAP Authentication" @@ -2165,19 +2331,19 @@ msgstr "Senha de Administrador LDAP" #: cps/templates/config_edit.html:253 msgid "LDAP Distinguished Name (DN)" -msgstr "Nome distinto LDAP (DN)" +msgstr "Nome Distinto LDAP (DN)" #: cps/templates/config_edit.html:257 msgid "LDAP User Object Filter" -msgstr "Filtro de objeto do usuário LDAP" +msgstr "Filtro de Objeto do Usuário LDAP" #: cps/templates/config_edit.html:262 msgid "LDAP Server is OpenLDAP?" -msgstr "O LDAP Server é 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 do usuário" +msgstr "As seguintes configurações são necessárias para a mportação de Usuários" #: cps/templates/config_edit.html:266 msgid "LDAP Group Object Filter" @@ -2210,7 +2376,7 @@ msgstr "Filtro de Utilizador Membro LDAP" #: cps/templates/config_edit.html:297 #, python-format msgid "Obtain %(provider)s OAuth Credential" -msgstr "Obtenha a credencial OAuth de %(provider)s" +msgstr "Obter credenciais OAuth de %(provider)s" #: cps/templates/config_edit.html:300 #, python-format @@ -2220,7 +2386,7 @@ msgstr "ID do cliente OAuth de %(provider)s" #: cps/templates/config_edit.html:304 #, python-format msgid "%(provider)s OAuth Client Secret" -msgstr "%(provider)s Cliente segredo do OAuth" +msgstr "Senha do cliente Oauth de %(provider)s" #: cps/templates/config_edit.html:320 msgid "External binaries" @@ -2232,7 +2398,7 @@ msgstr "Caminho para o Calibre E-Book Converter" #: cps/templates/config_edit.html:334 msgid "Calibre E-Book Converter Settings" -msgstr "Configurações do conversor de E-Book Calibre" +msgstr "Configurações do Calibre E-Book Converter" #: cps/templates/config_edit.html:337 msgid "Path to Kepubify E-Book Converter" @@ -2240,11 +2406,57 @@ msgstr "Caminho para Kepubify E-Book Converter" #: cps/templates/config_edit.html:345 msgid "Location of Unrar binary" -msgstr "Localização do binário Unrar" +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 "Ver configuração" +msgstr "Configuração de Visualização" #: cps/templates/config_view_edit.html:32 msgid "No. of Random Books to Display" @@ -2252,9 +2464,9 @@ msgstr "Nº de Livros Aleatórios a 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=Esconder Desativado)" +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" @@ -2264,7 +2476,7 @@ msgstr "Tema Padrão" #: cps/templates/config_view_edit.html:43 msgid "caliBlur! Dark Theme" -msgstr "caliBlur! Tema Negro" +msgstr "Tema caliBlur! Dark" #: cps/templates/config_view_edit.html:47 msgid "Regular Expression for Ignoring Columns" @@ -2272,7 +2484,7 @@ msgstr "Expressão Regular para Ignorar Colunas" #: cps/templates/config_view_edit.html:51 msgid "Link Read/Unread Status to Calibre Column" -msgstr "Ligar o estado de leitura/análise à coluna Calibre" +msgstr "Ligar Lido/Não Lido à coluna Calibre" #: cps/templates/config_view_edit.html:60 msgid "View Restrictions based on Calibre column" @@ -2280,11 +2492,11 @@ 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 classificação de títulos" +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ções padrão para novos usuários" +msgstr "Configuração padrão para novos usuários" #: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 msgid "Admin User" @@ -2296,7 +2508,7 @@ msgstr "Permitir Downloads" #: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 msgid "Allow eBook Viewer" -msgstr "Permitir que o eBook Viewer" +msgstr "Permitir Visualizador de eBook" #: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 msgid "Allow Uploads" @@ -2308,121 +2520,123 @@ msgstr "Permitir Editar" #: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 msgid "Allow Delete Books" -msgstr "Permitir Livros Excluídos" +msgstr "Permitir Apagar Livros" #: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 msgid "Allow Changing Password" -msgstr "Permitir mudança de senha" +msgstr "Permitir Alterar Senha" #: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 msgid "Allow Editing Public Shelves" -msgstr "Permitir a Edição de Prateleiras Públicas" +msgstr "Permitir a Edição de Estantes Públicas" #: cps/templates/config_view_edit.html:123 -#, fuzzy msgid "Default Language" -msgstr "Excluir idiomas" +msgstr "Idioma Padrão" #: cps/templates/config_view_edit.html:131 -#, fuzzy msgid "Default Visible Language of Books" -msgstr "Língua dos Livros" +msgstr "Idioma Padrão dos Livros Visíveis" #: cps/templates/config_view_edit.html:147 msgid "Default Visibilities for New Users" -msgstr "Visibilidades por defeito para novos utilizadores" +msgstr "Visibilidade Padrão para Novos Usuários" #: 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 Aleatórios em Vista de Detalhe" +msgstr "Mostrar Livros Aleatórios 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" +msgstr "Adicionar Tags Permitidas/Negadas" #: cps/templates/config_view_edit.html:167 msgid "Add Allowed/Denied custom column values" -msgstr "Adicionar valores permitidos/negados da coluna personalizada" +msgstr "Adicionar Valores Permitidos/Negados de Coluna Personalizada" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Ler no Browser" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Ouvir no Browser" -#: cps/templates/detail.html:124 -#, fuzzy, python-format +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 +#, python-format msgid "Book %(index)s of %(range)s" -msgstr "" +msgstr "Livro %(index)s de %(range)s" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicado em" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" -msgstr "Marcar como não lido" +msgstr "Marcar como Não Lido" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" -msgstr "Marcar como lido" +msgstr "Marcar como Lido" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Lido" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restaurar do arquivo" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Adicionar ao arquivo" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" -msgstr "Arquivado em" +msgstr "Arquivado" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descrição:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Editar Metadados" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" -msgstr "" +msgid "Email Account Type" +msgstr "Escolha o Tipo do Servidor" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" -msgstr "" +#, 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 "" +#, fuzzy +msgid "Gmail Account" +msgstr "Conta Gmail" #: 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 msgid "Revoke Gmail Access" -msgstr "" +msgstr "Revogar Acesso ao GMail" #: cps/templates/email_edit.html:42 msgid "STARTTLS" @@ -2438,20 +2652,21 @@ msgstr "Senha SMTP" #: cps/templates/email_edit.html:58 msgid "Attachment Size Limit" -msgstr "Limite do tamanho do anexo" +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:29 +#: 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 (Whitelist)" +msgstr "Domínios Permitidos (Lista Branca)" #: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 msgid "Add Domain" @@ -2460,7 +2675,7 @@ 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 "Adicione" +msgstr "Adicionar" #: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 msgid "Enter domainname" @@ -2468,209 +2683,215 @@ msgstr "Digite o nome do domínio" #: cps/templates/email_edit.html:92 msgid "Denied Domains (Blacklist)" -msgstr "Domínios negados (Blacklist)" +msgstr "Domínios Negados (Lista Negra)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 -#, fuzzy msgid "Kobo Token:" -msgstr "Kobo Sync Token" +msgstr "Token Kobo:" -#: cps/templates/http_error.html:31 -#, fuzzy +#: 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 "O servidor de E-Mail não está configurado, por favor contacte o seu administrador!" +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 Edição" +msgstr "Criar Issue" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" -msgstr "Voltar para casa" +msgstr "Voltar para Início" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" -msgstr "" +msgstr "Deslogar" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" -msgstr "" +msgstr "Ordenar em ordem crescente de acordo com a contagem de downloads" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" -msgstr "" - -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 -msgid "Sort authors in alphabetical order" -msgstr "Ordenar os autores em ordem alfabética" +msgstr "Ordenar em ordem decrescente de acordo com a contagem de downloads" #: cps/templates/index.html:78 cps/templates/search.html:35 #: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "Ordenar Autores em 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 os autores em ordem alfabética inversa" +msgstr "Ordenar Autores em ordem alfabética inversa" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" -msgstr "Ordenar ascendente de acordo com o índice de série" +msgstr "Ordenar em ordem crescente de acordo com o índice de série" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 msgid "Sort descending according to series index" -msgstr "Ordenação decrescente de acordo com o índice de série" +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 "" +msgstr "Livros Alfabéticos" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" -msgstr "" +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 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 encomendados pelo Autor" +msgstr "Livros ordenados por Autor" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" -msgstr "Livros encomendados pela editora" +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 encomendados por série" +msgstr "Livros ordenados por série" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" -msgstr "Livros encomendados por Idiomas" +msgstr "Livros ordenados por Idiomas" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" -msgstr "Livros encomendados por 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:135 -#: 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 "Prateleiras" +msgstr "Estantes" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" -msgstr "Livros organizados em prateleiras" +msgstr "Livros organizados em Estantes" -#: cps/templates/layout.html:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Início" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" -msgstr "Alternar a navegação" +msgstr "Alternar Navegação" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" -msgstr "Biblioteca de Pesquisa" +msgstr "Pesquisar na Biblioteca" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 "Enviando..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Erro" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." -msgstr "Upload feito, processando, por favor aguarde ..." +msgstr "Upload concluído, processando, por favor aguarde ..." -#: cps/templates/layout.html:76 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 "Configurações" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Conta" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Sair" - -#: cps/templates/layout.html:118 +#: 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:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Navegue em" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Sobre" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Anterior" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Detalhes do Livro" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Grade" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Lembre-se de mim" #: cps/templates/login.html:23 msgid "Forgot Password?" -msgstr "Esqueceu-se da senha?" +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" #: cps/templates/logviewer.html:6 msgid "Show Calibre-Web Log: " -msgstr "Mostrar Calibre-Web Log: " +msgstr "Mostrar Log Calibre-Web: " #: cps/templates/logviewer.html:8 msgid "Calibre-Web Log: " -msgstr "Calibre-Web Log: " +msgstr "Log Calibre-Web: " #: cps/templates/logviewer.html:8 msgid "Stream output, can't be displayed" @@ -2678,31 +2899,31 @@ msgstr "Saída do fluxo, não pode ser exibida" #: cps/templates/logviewer.html:12 msgid "Show Access Log: " -msgstr "Mostrar registo de acesso: " +msgstr "Mostrar Log de Acesso: " #: cps/templates/logviewer.html:18 msgid "Download Calibre-Web Log" -msgstr "Baixar Calibre-Web Log" +msgstr "Baixar Log Calibre-Web" #: cps/templates/logviewer.html:21 msgid "Download Access Log" -msgstr "Download do Log de Acesso" +msgstr "Baixar Log de Acesso" #: cps/templates/modal_dialogs.html:6 msgid "Select Allowed/Denied Tags" -msgstr "Selecione Etiquetas permitidas/negadas" +msgstr "Selecione Tags Permitidas/Negadas" #: cps/templates/modal_dialogs.html:7 msgid "Select Allowed/Denied Custom Column Values" -msgstr "Selecione Valores Permitidos/Não Permitidos da Coluna Personalizada" +msgstr "Selecione Valores Permitidos/Negadaos da Coluna Personalizada" #: cps/templates/modal_dialogs.html:8 msgid "Select Allowed/Denied Tags of User" -msgstr "Selecione Etiquetas de usuário permitidas/negadas" +msgstr "Selecione Tags de usuário Permitidas/Negadas" #: cps/templates/modal_dialogs.html:9 msgid "Select Allowed/Denied Custom Column Values of User" -msgstr "Selecione Valores de Coluna Personalizada Permitidos/Denegados do Usuário" +msgstr "Selecione Valores de Coluna Personalizada Permitidos/Negados do Usuário" #: cps/templates/modal_dialogs.html:15 msgid "Enter Tag" @@ -2710,15 +2931,15 @@ msgstr "Digite a tag" #: cps/templates/modal_dialogs.html:24 msgid "Add View Restriction" -msgstr "Adicionar restrição de visualização" +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á permanentemente apagado da base de dados" +msgstr "Este formato de livro será apagado permanentemente do banco 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" +msgstr "Este livro será apagado permanentemente do banco de dados" #: cps/templates/modal_dialogs.html:52 msgid "and hard disk" @@ -2726,7 +2947,7 @@ 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 Nota: os livros apagados permanecerão em qualquer dispositivo Kobo emparelhado." +msgstr "Nota importante Kobo: os livros apagados permanecerão em qualquer dispositivo Kobo emparelhado." #: cps/templates/modal_dialogs.html:57 msgid "Books must first be archived and the device synced before a book can safely be deleted." @@ -2734,7 +2955,7 @@ msgstr "Os livros devem primeiro ser arquivados e o dispositivo deve ser sincron #: cps/templates/modal_dialogs.html:76 msgid "Choose File Location" -msgstr "Escolha a localização do arquivo" +msgstr "Escolha a Localização do Arquivo" #: cps/templates/modal_dialogs.html:82 msgid "type" @@ -2750,165 +2971,192 @@ msgstr "tamanho" #: cps/templates/modal_dialogs.html:90 msgid "Parent Directory" -msgstr "Diretório dos Pais" +msgstr "Diretório Acima" #: cps/templates/modal_dialogs.html:98 msgid "Select" msgstr "Selecione" -#: cps/templates/modal_dialogs.html:134 -#, fuzzy +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" -msgstr "Livro" +msgstr "Ok" #: cps/templates/osd.xml:5 msgid "Calibre-Web eBook Catalog" msgstr "Catálogo de e-books Calibre-Web" #: cps/templates/read.html:6 -#, fuzzy msgid "epub Reader" -msgstr "leitor de PDF" +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:75 +#: 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 "Refluxo de texto quando as barras laterais estão abertas." +msgstr "Refluir o texto quando as barras laterais estiverem abertas." -#: cps/templates/readcbr.html:7 -#, fuzzy +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" -msgstr "leitor de PDF" +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 "Escala ao Melhor" +msgstr "Dimensionar para Melhor" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" -msgstr "Escala à Largura" +msgstr "Dimensionar para Largura" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" -msgstr "Escala à Altura" +msgstr "Dimensionar para Altura" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" -msgstr "Escala para Nativo" +msgstr "Dimensionar para a Nativo" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" -msgstr "Rodar para a direita" +msgstr "Girar para direita" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" -msgstr "Rodar para a esquerda" +msgstr "Girar para esqueda" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" -msgstr "Flip Image" +msgstr "Inverter Imagem" -#: cps/templates/readcbr.html:116 -msgid "Light" -msgstr "Luz" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Escuro" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Página única" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" -msgstr "Balança" +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 "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 "Da direita para a esquerda" +msgstr "Direita para a esquerda" -#: 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 "" +msgstr "Barra de Rolagem" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" -msgstr "" +msgstr "Mostrar" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" -msgstr "" +msgstr "Esconder" #: cps/templates/readdjvu.html:5 -#, fuzzy msgid "DJVU Reader" -msgstr "leitor de PDF" +msgstr "leitor de DJVU" -#: cps/templates/readpdf.html:29 -#, fuzzy +#: cps/templates/readpdf.html:32 msgid "PDF Reader" -msgstr "leitor de PDF" +msgstr "Leitor de PDF" #: cps/templates/readtxt.html:6 -#, fuzzy msgid "txt Reader" -msgstr "leitor de PDF" +msgstr "Leitor de TXT" #: cps/templates/register.html:4 msgid "Register New Account" @@ -2919,12 +3167,12 @@ 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 msgid "Magic Link - Authorise New Device" -msgstr "Magic Link - Autorizar novo dispositivo" +msgstr "Magic Link - Autorizar Novo Dispositivo" #: cps/templates/remote_login.html:7 msgid "On another device, login and visit:" @@ -2936,17 +3184,21 @@ msgstr "Uma vez verificado, você será automaticamente conectado a este disposi #: cps/templates/remote_login.html:14 msgid "This verification link will expire in 10 minutes." -msgstr "Este link de verificação expirará dentro de 10 minutos." +msgstr "Este link de verificação irá expirar em 10 minutos." -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Gerar miniaturas de capa de Série" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Nenhum resultado encontrado" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Termo de busca:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Resultados para:" @@ -2958,74 +3210,81 @@ 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 Etiquetas" +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 -#, fuzzy +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" -msgstr "Excluir Série" +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 "Classificação Acima" +msgstr "Avaliação Acima" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" -msgstr "Classificação Abaixo" +msgstr "Avaliação Abaixo" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" -msgstr "" +msgstr "De:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" -msgstr "" +msgstr "Para:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" -msgstr "Excluir esta estante" +msgstr "Apagar esta estante" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" -msgstr "Editar as propriedades da estante" +msgstr "Editar Propriedades da Estante" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Organizar os livros manualmente" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" -msgstr "Desativar ordem de modificação" +msgstr "Desabilitar Alterar Ordem" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" -msgstr "Habilitar ordem de modificação" +msgstr "Habilitar Alterar Ordem" #: cps/templates/shelf_edit.html:14 msgid "Share with Everyone" -msgstr "Partilhar com Todos" +msgstr "Compartilhar com Todos" #: cps/templates/shelf_edit.html:21 msgid "Sync this shelf with Kobo device" -msgstr "" +msgstr "sincronizar esta Estante com o Dispositivo Kobo" #: cps/templates/shelf_order.html:5 msgid "Drag to Rearrange Order" @@ -3060,8 +3319,8 @@ msgid "System Statistics" msgstr "Estatísticas do Sistema" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Biblioteca de programas" +msgid "Program" +msgstr "Programa" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3087,9 +3346,17 @@ 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" + +#: 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á salvo." + +#: 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" @@ -3097,7 +3364,7 @@ msgstr "Redefinir senha do usuário" #: cps/templates/user_edit.html:43 msgid "Language of Books" -msgstr "Língua dos Livros" +msgstr "Idioma dos Livros" #: cps/templates/user_edit.html:54 msgid "OAuth Settings" @@ -3109,11 +3376,11 @@ msgstr "Link" #: cps/templates/user_edit.html:58 msgid "Unlink" -msgstr "Desbloqueio" +msgstr "Desvincular" #: cps/templates/user_edit.html:64 msgid "Kobo Sync Token" -msgstr "Kobo Sync Token" +msgstr "Token de Sincronização Kobo" #: cps/templates/user_edit.html:66 msgid "Create/View" @@ -3121,125 +3388,109 @@ msgstr "Criar/Ver" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" -msgstr "" +msgstr "Forçar sincronização completa Kobo" #: cps/templates/user_edit.html:88 msgid "Add allowed/Denied Custom Column Values" -msgstr "Adicionar valores permitidos/definidos da coluna personalizada" +msgstr "Adicionar valores Permitidos/Negados da coluna personalizada" #: cps/templates/user_edit.html:137 msgid "Sync only books in selected shelves with Kobo" -msgstr "" +msgstr "Sincronizar apenas livros em estantes selecionadas com Kobo" #: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 msgid "Delete User" -msgstr "Eliminar Utilizador" +msgstr "Apagar Usuário" #: cps/templates/user_edit.html:159 msgid "Generate Kobo Auth URL" -msgstr "Gerar o Kobo Auth URL" +msgstr "Gerar URL de Autenticação Kobo" #: cps/templates/user_table.html:80 cps/templates/user_table.html:103 -#, fuzzy msgid "Select..." -msgstr "Selecione" +msgstr "Selecione..." #: cps/templates/user_table.html:131 -#, fuzzy msgid "Edit User" -msgstr "Usuário Admin" +msgstr "Editar Usuário" #: cps/templates/user_table.html:134 -#, fuzzy msgid "Enter Username" msgstr "Escolha um nome de usuário" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Seu endereço de e-mail" +msgid "Enter Email" +msgstr "E-mail de teste" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter Kindle E-mail Address" -msgstr "Enviar para o endereço de e-mail do Kindle" +msgid "Enter eReader Email" +msgstr "Enviar para o endereço de e-mail do E-Reader" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" -msgstr "E-mail de teste" +msgid "eReader Email" +msgstr "E-mail do E-Reader" #: cps/templates/user_table.html:137 -#, fuzzy msgid "Locale" -msgstr "Balança" +msgstr "Idioma" #: cps/templates/user_table.html:138 msgid "Visible Book Languages" -msgstr "" +msgstr "Idiomas dos Livros Visíveis" #: cps/templates/user_table.html:139 -#, fuzzy msgid "Edit Allowed Tags" -msgstr "Selecione Etiquetas permitidas/negadas" +msgstr "Editar Tags Permitidas" #: cps/templates/user_table.html:139 msgid "Allowed Tags" -msgstr "" +msgstr "Tags Permitidas" #: cps/templates/user_table.html:140 -#, fuzzy msgid "Edit Denied Tags" -msgstr "Selecione Etiquetas permitidas/negadas" +msgstr "Editar Tags Não Permitidas" #: cps/templates/user_table.html:140 msgid "Denied Tags" -msgstr "" +msgstr "Tags Não Permitidas" #: cps/templates/user_table.html:141 -#, fuzzy msgid "Edit Allowed Column Values" -msgstr "Adicionar valores permitidos/negados da coluna personalizada" +msgstr "Editar Valores de Coluna Permitidos" #: cps/templates/user_table.html:141 -#, fuzzy msgid "Allowed Column Values" -msgstr "Adicionar valores permitidos/negados da coluna personalizada" +msgstr "Valores de Coluna Permitidos" #: cps/templates/user_table.html:142 -#, fuzzy msgid "Edit Denied Column Values" -msgstr "Adicionar valores permitidos/negados da coluna personalizada" +msgstr "Editar Valores de Coluna Não Permitidos" #: cps/templates/user_table.html:142 -#, fuzzy msgid "Denied Column Values" -msgstr "Adicionar valores permitidos/negados da coluna personalizada" +msgstr "Valores de Coluna Não Permitidos" #: cps/templates/user_table.html:144 -#, fuzzy msgid "Change Password" -msgstr "Permitir mudança de senha" +msgstr "Alterar senha" #: cps/templates/user_table.html:147 msgid "View" -msgstr "" +msgstr "Ver" #: cps/templates/user_table.html:150 -#, fuzzy msgid "Edit Public Shelves" -msgstr "Estante Pública" +msgstr "Editar Estantes Públicas" #: cps/templates/user_table.html:152 msgid "Sync selected Shelves with Kobo" -msgstr "" +msgstr "Sincronizar Estantes Selecionadas com Kobo" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" -msgstr "Mostrar selecção de séries" - -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Mostrar livros aleatórios" +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 68a9eb31..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 a9077290..5e1bcf29 100644 --- a/cps/translations/ru/LC_MESSAGES/messages.po +++ b/cps/translations/ru/LC_MESSAGES/messages.po @@ -8,604 +8,648 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Статистика" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Сервер перезагружен, пожалуйста, обновите страницу" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Производится остановка сервера, пожалуйста, закройте окно" -#: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "Успешно переподключено" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Неизвестная команда" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Книга успешно поставлена в очередь для отправки на %(eReadermail)s" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Администрирование" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Настройки сервера" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Настройка интерфейса" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Управление сервером" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Все" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Конфигурация Calibre-Web обновлена" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Вы действительно хотите удалить Kobo Token ?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:599 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Вы действительно хотите остановить Calibre-Web?" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json не настроен для веб-приложения" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Неправильное расположение файла журнала, пожалуйста, введите правильный путь." -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Недопустимое расположение файла журнала доступа, пожалуйста, введите правильный путь" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Пожалуйста, введите провайдера LDAP, порт, DN и идентификатор объекта пользователя" -#: cps/admin.py:1146 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Пожалуйста, введите действительное имя пользователя для сброса пароля" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Фильтр объектов группы LDAP должен иметь один идентификатор формата \"%s\"" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Фильтр объектов группы LDAP имеет незавершённые круглые скобки" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Фильтр объектов пользователя LDAP должен иметь один идентификатор формата \"%s\"" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Фильтр объектов пользователя LDAP имеет незавершенную круглую скобку" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Добавить нового пользователя" -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "Расположение Базы Данных неверно, пожалуйста, введите правильный путь." +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Изменить настройки SMTP" -#: cps/admin.py:1253 -msgid "DB is not Writeable" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "Расположение ключевого файла неверно, пожалуйста, введите правильный путь" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "Расположение Certfile не является действительным, пожалуйста, введите правильный путь" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "Настройки E-mail сервера обновлены" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Дополнительный Настройки" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Пожалуйста, заполните все поля!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-mail не из существующей доменной зоны" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Добавить пользователя" - -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" -msgstr "Пользователь '%(user)s' добавлен" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Для этого адреса электронной почты или логина уже есть учётная запись." +msgid "Oops! Database Error: %(error)s." +msgstr "" -#: cps/admin.py:1463 +#: cps/admin.py:1323 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "Пользователь '%(nick)s' удалён" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Это последний администратор, невозможно удалить пользователя" - -#: cps/admin.py:1542 cps/admin.py:1667 +#: cps/admin.py:1326 #, python-format -msgid "Edit User %(nick)s" -msgstr "Изменить пользователя %(nick)s" +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Произошла ошибка при отправке тестового письма на: %(res)s" -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Пользователь '%(nick)s' обновлён" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Пожалуйста, сначала настройте свой адрес электронной почты ..." -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Неизвестная ошибка. Попробуйте позже." +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Настройки E-mail сервера обновлены" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Изменить настройки SMTP" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1633 -#, python-format -msgid "There was an error sending the Test e-mail: %(res)s" -msgstr "Произошла ошибка при отправке тестового письма на: %(res)s" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." -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:1637 -msgid "E-mail server settings updated" -msgstr "Настройки E-mail сервера обновлены" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Изменить пользователя %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Пароль для пользователя %(user)s сброшен" -#: cps/admin.py:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Просмотр лога" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Проверка обновлений" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Загрузка обновлений" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Распаковка обновлений" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Замена файлов" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Соединения с базой данных закрыты" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Остановка сервера" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Обновления установлены, нажмите ок и перезагрузите страницу" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Ошибка HTTP" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Ошибка соединения" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Тайм-аут при установлении соединения" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Общая ошибка" -#: cps/admin.py:1773 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Не удалось сохранить файл обновления во временной папке." -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Не удалось создать хотя бы одного пользователя LDAP" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Не удалось создать хотя бы одного пользователя LDAP" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Ошибка: %(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Ошибка: ни одного пользователя не найдено в ответ на запрос сервер LDAP" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "По крайней мере, один пользователь LDAP не найден в базе данных" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "Расположение Базы Данных неверно, пожалуйста, введите правильный путь." + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Расположение ключевого файла неверно, пожалуйста, введите правильный путь" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Расположение Certfile не является действительным, пожалуйста, введите правильный путь" + +#: 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:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Дополнительный Настройки" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Пожалуйста, заполните все поля!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-mail не из существующей доменной зоны" + +#: 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:1926 +#, fuzzy +msgid "Oops! An account already exists for this Email. or name." +msgstr "Для этого адреса электронной почты или логина уже есть учётная запись." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Пользователь '%(nick)s' удалён" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +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:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Пользователь '%(nick)s' обновлён" + +#: cps/converter.py:31 msgid "not installed" msgstr "не установлено" -#: cps/converter.py:31 +#: cps/converter.py:32 msgid "Execution permissions missing" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:917 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:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 +#: 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:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: 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:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Метаданные обновлены" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Невозможно открыть книгу. Файл не существует или недоступен" +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Файл %(file)s загружен" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "изменить метаданные" +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Исходный или целевой формат для конвертирования отсутствует" -#: cps/editbooks.py:457 +#: cps/editbooks.py:337 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "" +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Книга успешно поставлена в очередь для конвертирования в %(book_format)s" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Произошла ошибка при конвертирования этой книги: %(res)s" + +#: cps/editbooks.py:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "Загруженная книга, вероятно, существует в библиотеке, перед тем как загрузить новую, рассмотрите возможность изменения: " + +#: 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:634 -msgid "User has no rights to upload additional file formats" -msgstr "" - -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: 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:643 cps/editbooks.py:1033 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Загружаемый файл должен иметь расширение" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Ошибка при создании пути %(path)s (Доступ запрещён)." - -#: cps/editbooks.py:660 +#: cps/editbooks.py:753 #, python-format -msgid "Failed to store file %(file)s." -msgstr "Не удалось сохранить файл %(file)s." +msgid "File %(filename)s could not saved to temp dir" +msgstr "Файл %(filename)s не удалось сохранить во временную папку" -#: cps/editbooks.py:683 +#: cps/editbooks.py:773 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Формат файла %(ext)s добавлен в %(book)s" - -#: cps/editbooks.py:697 cps/editbooks.py:809 -msgid "User has no rights to upload cover" +msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:828 -msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:869 -msgid "Metadata successfully updated" -msgstr "Метаданные обновлены" +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "" -#: cps/editbooks.py:887 -msgid "Error editing book: {}" +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:951 -msgid "Uploaded book probably exists in the library, consider to change before upload new: " -msgstr "Загруженная книга, вероятно, существует в библиотеке, перед тем как загрузить новую, рассмотрите возможность изменения: " +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "изменить метаданные" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:992 #, python-format -msgid "File %(filename)s could not saved to temp dir" -msgstr "Файл %(filename)s не удалось сохранить во временную папку" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" -#: cps/editbooks.py:1061 -#, python-format -msgid "Failed to Move Cover File %(file)s: %(error)s" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:1195 #, python-format -msgid "File %(file)s uploaded" -msgstr "Файл %(file)s загружен" - -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Исходный или целевой формат для конвертирования отсутствует" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Ошибка при создании пути %(path)s (Доступ запрещён)." -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1200 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Книга успешно поставлена в очередь для конвертирования в %(book_format)s" +msgid "Failed to store file %(file)s." +msgstr "Не удалось сохранить файл %(file)s." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1224 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Произошла ошибка при конвертирования этой книги: %(res)s" +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" @@ -620,187 +664,182 @@ msgstr "Не удалось проверить домен обратного в 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Отправить на Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Тестовый e-mail для Calibre-Web" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Тестовый e-mail" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Начать работу с Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 и отправить в Kindle" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Отправить %(format)s в Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Отправить на Kindle" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Запрашиваемый файл не может быть прочитан. Возможно у вас нет разрешения?" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Путь книги %(path)s не найден на Google Drive" -#: cps/helper.py:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Это имя пользователя уже занято" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Не удалось создать путь для обложки." -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Только файлы в формате jpg / jpeg поддерживаются как файл обложки" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Ожидание" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Неудачно" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Начало" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Завершено" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Обзор" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Неизвестный статус" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Настройка Kobo" @@ -809,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:1613 +#: 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 @@ -870,12 +909,13 @@ msgstr "Ошибка Google Oauth, пожалуйста попробуйте п msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "Логин" @@ -891,497 +931,619 @@ msgstr "Ключ просрочен" msgid "Success! Please return to your device" msgstr "Успешно! Пожалуйста, проверьте свое устройство" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Книги" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Показывать недавние книги" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Популярные Книги" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Показывать популярные книги" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Книги с наилучшим рейтингом" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Показывать прочитанные и непрочитанные" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Показать непрочитанное" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Обзор" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Рейтинги" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Форматы файлов" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Поиск" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Опубликовано после " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Опубликовано до " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Рейтинг <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Рейтинг >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Расширенный поиск" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Указана неверная полка" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Извините, но вам не разрешено добавлять книги на полку: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Книги уже размещены на полке: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Книга добавлена на книжную полку: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Книги уже размещены на полке: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Книги добавлены на полку: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Не удалось добавить книги на полку: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Книга удалена с полки: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Создать полку" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Извините, вы не можете удалить книгу с полки: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Изменить полку" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Метаданные обновлены" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Изменить расположение полки '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Создана полка %(title)s" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Колка %(title)s изменена" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Произошла ошибка" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Публичная полка с названием '%(title)s' уже существует." -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Приватная полка с названием '%(title)s' уже существует." -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Метаданные обновлены" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Изменить расположение полки '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Полка: '%(name)s'" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Ошибка открытия Полки. Полка не существует или недоступна" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Задания" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Ожидание" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Неудачно" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Начало" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Завершено" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: 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 "Некорректные данные при чтении информации об обновлении" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Нет доступных обновлений. Вы используете последнюю версию" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Новое обновление доступно. Нажмите на кнопку ниже, чтобы обновить до последней версии." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Не удалось получить информацию об обновлении" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Нажмите на кнопку ниже для обновления до последней стабильной версии." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Новое обновление доступно. Нажмите на кнопку ниже, чтобы обновиться до версии: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Информация о выпуске недоступна" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Обзор (Случайные Книги)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Популярные книги (часто загружаемые)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Автор: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Издатель: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Серии: %(serie)s" -#: cps/web.py:610 +#: 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:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Формат файла: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Категория: %(name)s" -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "Язык: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Расширенный поиск" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Поиск" +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Язык: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Скачать" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Список рейтингов" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Список форматов файлов" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Задания" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Опубликовано после " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Опубликовано до " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Рейтинг <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Рейтинг >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Пожалуйста, сперва настройте параметры SMTP....." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Книга успешно поставлена в очередь для отправки на %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Книга успешно поставлена в очередь для отправки на %(eReadermail)s" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Не удается активировать LDAP аутентификацию" -#: cps/web.py:1621 -#, 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:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Не удалось войти: %(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Ошибка в имени пользователя или пароле" -#: cps/web.py:1638 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Новый пароль был отправлен на ваш адрес электронной почты" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "Ошибка Ebook-конвертора: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "изменить метаданные" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Загрузить" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Список пользователей" @@ -1394,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Отправить на Kindle Адрес электронной почты" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Управление" @@ -1411,13 +1574,8 @@ msgstr "Управление" msgid "Password" msgstr "Пароль" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Загрузить" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "Скачать" @@ -1431,7 +1589,7 @@ msgstr "Посмотреть электронные книги" msgid "Edit" msgstr "Редактировать" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1442,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 @@ -1472,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 @@ -1544,78 +1698,109 @@ msgstr "Изменить основные настройки" msgid "Edit UI Configuration" msgstr "Изменить настройки интерфейса" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Просмотреть лог файл" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Пере подключиться к базе жанных Calibre" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Перезагрузить Calibre-Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Остановить Calibre-Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Обновление" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Версия" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Подробности" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Текущая версия" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Проверка обновлений" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Установить обновления" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Вы действительно хотите перезагрузить Calibre-Web?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Вы действительно хотите остановить Calibre-Web?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Установка обновлений, пожалуйста, не обновляйте страницу" @@ -1627,39 +1812,39 @@ msgstr "с помощью" msgid "In Library" msgstr "В библиотеке" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "уменьшить" @@ -1667,165 +1852,166 @@ msgstr "уменьшить" msgid "More by" msgstr "Ещё от" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Удалить книгу" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Удалить форматы:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Конвертировать формат книги:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Конвертировать из:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "выбрать вариант" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Конвертировать в:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Конвертировать книгу" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Название книги" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Автор" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Описание" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Теги" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "ID Серии" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Рейтинг" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "URL обложки(jpg, обложка загружается и сохраняется в базе данных, после этого поле снова пустое)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Загрузить обложку с диска" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Опубликовано" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Издатель" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "Нет" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Загружаемый формат" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Просмотреть книгу после сохранения" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Получить метаданные" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Сохранить" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Ключевое слово" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Поиск по ключевому слову " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Нажмите на обложку, чтобы получить метаданные" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Загрузка..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "Закрыть" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Источник" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Ошибка поиска!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Результат(ы) не найдены! Попробуйте другое ключевое слово." @@ -1918,7 +2104,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1934,6 +2120,7 @@ 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 "Вы действительно уверены?" @@ -2039,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 @@ -2055,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 @@ -2245,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 "Просмотреть Конфигурацию" @@ -2257,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 "Тема" @@ -2348,79 +2581,82 @@ msgstr "Добавить разрешенные / запрещенные тег msgid "Add Allowed/Denied custom column values" msgstr "Добавить разрешенные / запрещенные значения индивидуальных столбцов" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Читать" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Прослушать в браузере" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Опубликованный" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Отметить как непрочитанное" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Отметить как прочитанное" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Прочесть" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Описание:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Добавить на книжную полку" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2444,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:29 +#: 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 "Назад" @@ -2473,12 +2710,12 @@ msgstr "Введите доменное имя" msgid "Denied Domains (Blacklist)" msgstr "Запрещенные домены (черный список)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 @@ -2486,175 +2723,183 @@ msgstr "Откройте файл .kobo / Kobo eReader.conf в текстово msgid "Kobo Token:" msgstr "Kobo Sync Token" -#: cps/templates/http_error.html:31 +#: 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 "Сервер электронной почты не настроен, обратитесь к администратору !" -#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Главная" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Включить навигацию" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Поиск в библиотеке" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "Загружается..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Ошибка" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Загрузка завершена, обработка, пожалуйста, подождите..." -#: cps/templates/layout.html:76 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 "Настройки" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Учетная запись" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Выход" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Пожалуйста не обновляйте страницу" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Просмотр" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "О программе" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Предыдущий" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Подробнее о книге" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Запомнить меня" @@ -2663,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 "Войти через магическую ссылку" @@ -2759,7 +3004,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Книга" @@ -2773,128 +3018,162 @@ msgstr "Каталог электронных книг Caliber-Web" msgid "epub Reader" msgstr "PDF reader" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Светлая" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "Назад" + +#: 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:116 -msgid "Light" -msgstr "Светлая" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Темная" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Администрирование" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2903,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" @@ -2922,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 @@ -2941,15 +3220,19 @@ msgstr "После этого вы автоматически войдете в msgid "This verification link will expire in 10 minutes." msgstr "Срок действия ссылки истекает через 10 минут." -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Результаты не найдены" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Выражение для поиска:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Результаты для:" @@ -2961,64 +3244,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Удалить эту книжную полку" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3063,8 +3354,8 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Программа" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3090,9 +3381,17 @@ 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 "" + +#: 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" @@ -3158,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Отправить на Kindle Адрес электронной почты" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Тестовый e-mail" #: cps/templates/user_table.html:137 @@ -3238,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 1e216ed2..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 1a276632..0510f7d6 100644 --- a/cps/translations/sv/LC_MESSAGES/messages.po +++ b/cps/translations/sv/LC_MESSAGES/messages.po @@ -7,602 +7,645 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Statistik" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" -msgstr "Återanslutning lyckades" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "Okänt kommando" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Administrationssida" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Grundläggande konfiguration" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Användargränssnitt konfiguration" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Redigera användare" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Användaren hittades inte" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} användare har tagits bort" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Felaktig begäran" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Gästnamn kan inte ändras" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gäst kan inte ha den här rollen" -#: cps/admin.py:460 cps/admin.py:1484 +#: 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:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ogiltig roll" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gästen kan inte ha den här vyn" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ogiltig vy" -#: cps/admin.py:483 +#: 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:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Inget giltigt språk anges" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Inget giltigt bokspråk anges" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter hittades inte" -#: cps/admin.py:553 +#: cps/admin.py:571 #, fuzzy msgid "Invalid Read Column" msgstr "Ogiltig roll" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web konfiguration uppdaterad" -#: cps/admin.py:591 +#: 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:593 +#: 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:595 +#: 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:597 +#: 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:599 +#: 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:601 +#: 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:603 +#: 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:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: 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:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "Taggen hittades inte" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "Ogiltig åtgärd" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Taggen hittades inte" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Ogiltig åtgärd" + +#: 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:1104 +#: 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:1110 +#: 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:1140 +#: 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:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: 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:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP-gruppobjektfilter har omatchande parentes" -#: cps/admin.py:1160 +#: 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:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP-användarobjektfilter har omatchad parentes" -#: cps/admin.py:1169 +#: 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:1171 +#: 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:1178 +#: 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:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "Databasfel: %(error)s." - -#: cps/admin.py:1235 -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:1253 -msgid "DB is not Writeable" -msgstr "DB är inte skrivbar" - -#: cps/admin.py:1266 -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:1270 -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:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "E-postserverinställningar uppdaterade" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Funktion konfiguration" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Fyll i alla fält!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-posten är inte från giltig domän" - -#: cps/admin.py:1416 cps/admin.py:1576 -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:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "Användaren '%(user)s' skapad" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "Hittade ett befintligt konto för den här e-postadressen eller namnet." - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "Användaren '%(nick)s' borttagen" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "Det går inte att ta bort gästanvändaren" - -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Ingen adminstratörsanvändare kvar, kan inte ta bort användaren" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Ändra SMTP-inställningar" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Redigera användaren %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "Användaren '%(nick)s' uppdaterad" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Ett okänt fel uppstod. Försök igen senare." - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Ändra SMTP-inställningar" - -#: cps/admin.py:1604 -#, fuzzy -msgid "Gmail Account Verification Successful" -msgstr "Verifiering av G-mail-kontot lyckades" +msgid "Oops! Database Error: %(error)s." +msgstr "Databasfel: %(error)s." -#: cps/admin.py:1630 +#: 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:1633 +#: 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:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Vänligen konfigurera din e-postadress först..." -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "E-postserverinställningar uppdaterade" -#: cps/admin.py:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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 "Ett okänt fel uppstod. Försök igen senare." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Redigera användaren %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visaren för loggfil" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Begär uppdateringspaketet" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Hämtar uppdateringspaketet" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Packar upp uppdateringspaketet" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Ersätta filer" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databasanslutningarna är stängda" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Stoppar server" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Anslutningsfel" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Allmänt fel" -#: cps/admin.py:1773 +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: 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:1843 +#: 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:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fel: %(ldaperror)s" -#: cps/admin.py:1860 +#: 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:1893 +#: 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:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} användare har importerats" -#: cps/converter.py:30 -msgid "not installed" -msgstr "inte installerad" +#: 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/converter.py:31 -msgid "Execution permissions missing" -msgstr "Körningstillstånd saknas" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "DB är inte skrivbar" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "Anpassad kolumn n.%(column)d finns inte i calibre-databasen" +#: 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/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Ingen" +#: 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/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "Bokformat har tagits bort" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "Boken har tagits bort" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "E-postserverinställningar uppdaterade" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Funktion konfiguration" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title 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/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Fyll i alla fält!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "redigera metadata" +#: 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:1909 +msgid "Add new user" +msgstr "Lägg till ny användare" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "" +msgid "User '%(user)s' created" +msgstr "Användaren '%(user)s' skapad" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s är inte ett giltigt språk" +#: 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/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Användaren '%(nick)s' borttagen" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Det går inte att ta bort gästanvändaren" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, 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" +msgid "User '%(nick)s' updated" +msgstr "Användaren '%(nick)s' uppdaterad" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Filen som ska laddas upp måste ha en ändelse" +#: cps/converter.py:31 +msgid "not installed" +msgstr "inte installerad" -#: cps/editbooks.py:655 -#, 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/converter.py:32 +msgid "Execution permissions missing" +msgstr "Körningstillstånd saknas" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "Det gick inte att lagra filen %(file)s." +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "Filformatet %(ext)s lades till %(book)s" +#: 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:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: 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:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata uppdaterades" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Filen %(file)s uppladdad" + +#: 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: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: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: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:1041 +#: 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: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: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: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:1061 +#: 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:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Bokformat har tagits bort" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Boken har tagits bort" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "redigera metadata" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "Filen %(file)s uppladdad" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Källa eller målformat för konvertering saknas" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "Boken är i kö för konvertering till %(book_format)s" +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:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "Det gick inte att konvertera den här boken: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "Det gick inte att lagra filen %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Filformatet %(ext)s lades till %(book)s" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -617,186 +660,184 @@ msgstr "Återuppringningsdomänen är inte verifierad, följ stegen för att ver 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Skicka till Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Test e-post" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Kom igång med Calibre-Web" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +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:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Skicka %(format)s till Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Skicka till Kindle" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Detta användarnamn är redan taget" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Ogiltigt e-postadressformat" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Fel vid hämtning av omslaget" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Fel på omslagsformat" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: 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:799 +#: 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:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: 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:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar binär fil hittades inte" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "Fel vid körning av UnRar" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Väntar" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Misslyckades" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Startad" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Klar" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Upptäck" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Okänd status" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo-installation" @@ -805,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:1613 +#: 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 @@ -866,12 +907,13 @@ msgstr "Google Oauth-fel, försök igen senare." msgid "Google Oauth error: {}" msgstr "Google Oauth-fel: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} stjärnor" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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" @@ -887,497 +929,618 @@ 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Böcker" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Visa senaste böcker" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Visa heta böcker" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Hämtade böcker" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: 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:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Visa olästa" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Upptäck" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Betyg" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Filformat" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Arkiverade böcker" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Boklista" -#: cps/render_template.py:102 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/shelf.py:67 cps/shelf.py:121 +#: 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 "Publicerad efter " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publicerad före " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Betyg <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Betyg >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Lässtatus = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Avancerad sökning" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Ogiltig hylla specificerad" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Tyvärr får du inte lägga till en bok på hyllan: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "Boken är redan en del av hyllan: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Boken har lagts till i hyllan: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "Böcker är redan en del av hyllan: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "Böcker har lagts till hyllan: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "Kunde inte lägga till böcker till hyllan: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Boken har tagits bort från hyllan: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Skapa en hylla" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Tyvärr har du inte rätt att ta bort en bok från den här hyllan: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Redigera en hylla" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Boken har tagits bort" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Ändra ordning på hyllan: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Hyllan %(title)s skapad" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Hyllan %(title)s ändrad" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Det fanns ett fel" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Boken har tagits bort" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Ändra ordning på hyllan: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Hylla: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Uppgifter" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Väntar" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Misslyckades" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Startad" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Klar" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Okänd 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 "Oväntade data vid läsning av uppdateringsinformation" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Ingen uppdatering tillgänglig. Du har redan den senaste versionen installerad" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "En ny uppdatering är tillgänglig. Klicka på knappen nedan för att uppdatera till den senaste versionen." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Kunde inte hämta uppdateringsinformation" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Klicka på knappen nedan för att uppdatera till den senaste stabila versionen." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 uppdatering är tillgänglig. Klicka på knappen nedan för att uppdatera till version: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Ingen versionsinformation tillgänglig" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Upptäck (slumpmässiga böcker)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Heta böcker (mest hämtade)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Hämtade böcker av %(user)s" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Författare: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Förlag: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serier: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Betyg: %(rating)s stars" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Filformat: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategori: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" -msgstr "Språk: %(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Avancerad sökning" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Sök" +msgstr "Språk: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Hämtningar" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Betygslista" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista över filformat" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Uppgifter" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Publicerad efter " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Publicerad före " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Betyg <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "Betyg >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "Lässtatus = %(status)s" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Konfigurera SMTP-postinställningarna först..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Boken är i kö för att skicka till %(kindlemail)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:1531 +#: 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 "Det gick inte att skicka den här boken: %(res)s" -#: cps/web.py:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: 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:1621 +#: 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:1627 -#, 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:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Fel användarnamn eller lösenord" -#: cps/web.py:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "calibre e-bokkonverterings %(tool)s hittades inte" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "%(format)s-format hittades inte på disken" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "E-bokkonverteraren misslyckades med okänt fel" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify-konverteraren misslyckades: %(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "Konverterad fil hittades inte eller mer än en fil i mappen %(folder)s" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "E-bokkonverteraren misslyckades: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "calibre misslyckades med fel: %(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "redigera metadata" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Ladda upp" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Användarlista" @@ -1390,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Administratör" @@ -1407,13 +1571,8 @@ msgstr "Administratör" msgid "Password" msgstr "Lösenord" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Ladda upp" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1427,7 +1586,7 @@ msgstr "Visa e-böcker" msgid "Edit" msgstr "Redigera" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1438,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 @@ -1468,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 @@ -1540,78 +1696,109 @@ msgstr "Redigera grundläggande konfiguration" msgid "Edit UI Configuration" msgstr "Redigera UI-konfiguration" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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 "Administration" -#: cps/templates/admin.html:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Hämta felsökningspaketet" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Visa loggfiler" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "Anslut till Calibre DB igen" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Starta om Calibre-Web" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Stoppa Calibre-Web" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Uppdatera" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaljer" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Aktuell version" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Sök efter uppdatering" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Utför uppdatering" -#: cps/templates/admin.html:210 +#: 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:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: 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:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Uppdaterar, vänligen uppdatera inte sidan" @@ -1623,39 +1810,39 @@ msgstr "via" msgid "In Library" msgstr "I biblioteket" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "Sortera efter bokdatum, nyast först" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "Sortera efter bokdatum, äldsta först" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "Sortera titel i alfabetisk ordning" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "Sortera titel i omvänd alfabetisk ordning" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "Sortera efter publiceringsdatum, nyast först" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "Sortera efter publiceringsdatum, äldsta först" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "minska" @@ -1663,165 +1850,166 @@ msgstr "minska" msgid "More by" msgstr "Mer av" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Ta bort boken" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Ta bort format:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Konvertera bokformat:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Konvertera från:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "välj ett alternativ" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Konvertera till:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "Konvertera boken" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Boktitel" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Författare" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Beskrivning" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "Identifierare" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "Identifierartyp" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "Identifierarvärde" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: 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:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "Lägg till identifierare" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Taggar" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "Serie-ID" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Betyg" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "Omslagswebbadress (jpg, omslag hämtas och lagras i databasen, fältet är efteråt tomt igen)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "Ladda upp omslag från lokal enhet" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Publiceringsdatum" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Förlag" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Ladda upp format" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "Visa bok vid Spara" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Hämta metadata" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "Spara" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Sökord" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Sök sökord " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Klicka på omslaget för att läsa in metadata till formuläret" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Läser in..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Källa" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Sökningsfel!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "Inga resultat hittades! Försök med ett annat sökord." @@ -1914,7 +2102,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1930,6 +2118,7 @@ msgid "Enter " msgstr "Identifierare" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Är du verkligen säker?" @@ -2035,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 @@ -2051,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 @@ -2241,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" @@ -2253,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" @@ -2344,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:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Läs i webbläsaren" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Lyssna i webbläsaren" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicerad" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Markera som oläst" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Markera som läst" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Läst" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Återställ från arkivet" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Lägg till i arkivet" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Arkiverad" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beskrivning:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2441,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:29 +#: 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" @@ -2470,188 +2709,196 @@ msgstr "Ange domännamn" msgid "Denied Domains (Blacklist)" msgstr "Avvisade domäner för registrering" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Kobo Sync Token" -#: cps/templates/http_error.html:31 +#: 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-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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "Sortera författare i alfabetisk ordning" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "Sortera författare i omvänd alfabetisk ordning" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "Sortera stigande enligt serieindex" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Hem" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Växla navigering" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "Sök i bibliotek" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 "Logga ut" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Laddar upp..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Fel" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Uppladdning klar, bearbetning, vänligen vänta ..." -#: cps/templates/layout.html:76 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 "Inställningar" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Konto" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Logga ut" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Vänligen uppdatera inte sidan" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Bläddra" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Om" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Föregående" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Bokdetaljer" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Kom ihåg mig" @@ -2660,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" @@ -2756,7 +3003,7 @@ msgstr "Föräldramapp" msgid "Select" msgstr "Välj" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "Ok" @@ -2769,128 +3016,162 @@ msgstr "Calibre-Web e-bokkatalog" msgid "epub Reader" msgstr "PDF-läsare" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Ljust" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Mörkt" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Tillbaka" + +#: 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:116 -msgid "Light" -msgstr "Ljust" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Mörkt" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Administrationssida" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2899,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" @@ -2918,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 @@ -2937,15 +3218,19 @@ 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/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "Inga resultat hittades" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "Sökterm:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Resultat för:" @@ -2957,63 +3242,71 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Ta bort den här hyllan" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "Redigera hyllegenskaper" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "Ordna böcker manuellt" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "Inaktivera ändring av ordning" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "Aktivera ändring av ordning" @@ -3058,8 +3351,8 @@ msgid "System Statistics" msgstr "Systemstatistik" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Programbibliotek" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3085,9 +3378,17 @@ 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 "" + +#: 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" @@ -3150,16 +3451,19 @@ 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 -msgid "Enter Kindle E-mail Address" -msgstr "Ange Kindle e-postadress" +#, fuzzy +msgid "Enter eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "Kindle e-postadress" +#, fuzzy +msgid "eReader Email" +msgstr "Test e-post" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3220,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 50d23b6b..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 7234d5bb..5e4ea0ef 100644 --- a/cps/translations/tr/LC_MESSAGES/messages.po +++ b/cps/translations/tr/LC_MESSAGES/messages.po @@ -7,598 +7,642 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=2; plural=(n > 1)\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "İstatistikler" -#: cps/admin.py:141 -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:143 -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:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +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: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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Yönetim sayfası" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Temel Ayarlar" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Arayüz Ayarları" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: 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:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web yapılandırması güncellendi" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:607 +#: 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:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "" -#: cps/admin.py:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "" - -#: cps/admin.py:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: 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:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "E-posta sunucusu ayarları güncellendi" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Özellik Yapılandırması" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Lütfen tüm alanları doldurun!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "E-posta izin verilen bir servisten değil" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Yeni kullanıcı ekle" - -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" -msgstr "'%(user)s' kullanıcısı oluşturuldu" - -#: cps/admin.py:1433 -#, fuzzy -msgid "Found an existing account for this e-mail address or name." -msgstr "Bu e-posta adresi veya kullanıcı adı için zaten bir hesap var." +msgid "Oops! Database Error: %(error)s." +msgstr "" -#: cps/admin.py:1463 +#: cps/admin.py:1323 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "Kullanıcı '%(nick)s' silindi" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "Başka yönetici kullanıcı olmadığından silinemedi" - -#: cps/admin.py:1542 cps/admin.py:1667 +#: cps/admin.py:1326 #, python-format -msgid "Edit User %(nick)s" -msgstr "%(nick)s kullanıcısını düzenle" +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:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "'%(nick)s' kullanıcısı güncellendi" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Lütfen önce e-posta adresinizi ayarlayın..." -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "Bilinmeyen bir hata oluştu. Lütfen daha sonra tekrar deneyiniz." +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "E-posta sunucusu ayarları güncellendi" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1633 -#, 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:1380 +msgid "Scheduled tasks settings updated" +msgstr "" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." -msgstr "Lütfen önce e-posta adresinizi ayarlayın..." +#: 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:1637 -msgid "E-mail server settings updated" -msgstr "E-posta sunucusu ayarları güncellendi" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "%(nick)s kullanıcısını düzenle" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Log dosyası görüntüleyici" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Güncelleme paketi isteniyor" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Güncelleme paketi indiriliyor" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Güncelleme paketi ayıklanıyor" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Dosyalar değiştiriliyor" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Veritabanı bağlantıları kapalı" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Sunucu durduruyor" -#: cps/admin.py:1768 +#: 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:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Bağlantı hatası" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: 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:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Genel hata" -#: cps/admin.py:1773 +#: 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:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: 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:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Özellik Yapılandırması" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Lütfen tüm alanları doldurun!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-posta izin verilen bir servisten değil" + +#: 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:1926 +#, fuzzy +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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Kullanıcı '%(nick)s' silindi" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "" + +#: 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:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "'%(nick)s' kullanıcısı güncellendi" + +#: cps/converter.py:31 msgid "not installed" msgstr "yüklü değil" -#: cps/converter.py:31 +#: cps/converter.py:32 msgid "Execution permissions missing" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:917 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:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 +#: 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:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: 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:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/editbooks.py:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metaveri başarıyla güncellendi" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "metaveri düzenle" +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "%(file)s dosyası yüklendi" + +#: 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:457 +#: cps/editbooks.py:337 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "" +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: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:493 cps/editbooks.py:1001 +#: 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: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:634 -msgid "User has no rights to upload additional file formats" -msgstr "" - -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: 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:643 cps/editbooks.py:1033 +#: 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:655 +#: cps/editbooks.py:753 #, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "%(path)s dizini oluşturulamadı. (İzin reddedildi)" - -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "%(file)s dosyası kaydedilemedi." +msgid "File %(filename)s could not saved to temp dir" +msgstr "%(filename)s dosyası geçici dizine kaydedilemedi" -#: cps/editbooks.py:683 +#: cps/editbooks.py:773 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "%(book)s kitabına %(ext)s dosya biçimi eklendi" - -#: cps/editbooks.py:697 cps/editbooks.py:809 -msgid "User has no rights to upload cover" +msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:828 -msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:869 -msgid "Metadata successfully updated" -msgstr "Metaveri başarıyla güncellendi" +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "" -#: cps/editbooks.py:887 -msgid "Error editing book: {}" +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:951 -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:943 +msgid "edit metadata" +msgstr "metaveri düzenle" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:992 #, python-format -msgid "File %(filename)s could not saved to temp dir" -msgstr "%(filename)s dosyası geçici dizine kaydedilemedi" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" -#: cps/editbooks.py:1061 -#, python-format -msgid "Failed to Move Cover File %(file)s: %(error)s" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:1195 #, python-format -msgid "File %(file)s uploaded" -msgstr "%(file)s dosyası yüklendi" - -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "Dönüştürme için kaynak ya da hedef biçimi eksik" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "%(path)s dizini oluşturulamadı. (İzin reddedildi)" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1200 #, 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ı" +msgid "Failed to store file %(file)s." +msgstr "%(file)s dosyası kaydedilemedi." -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1224 #, 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" +msgid "File format %(ext)s added to %(book)s" +msgstr "%(book)s kitabına %(ext)s dosya biçimi eklendi" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" @@ -613,186 +657,181 @@ msgstr "Geri yönlendirme alanı (callback domain) doğrulanamadı, lütfen Goog 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Kindle'a gönder" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -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:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Deneme e-Postası" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Web'i Kullanmaya Başlayın" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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'dan %(format)s biçimine çevir ve Kindle'a gönder" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "%(format)s biçimlerini Kindle'a gönder" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Kindle'a gönder" -#: cps/helper.py:225 +#: 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:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -#, 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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Bu kullanıcı adı zaten alındı" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "Bekleniyor" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "Başarısız" - -#: cps/helper.py:941 -msgid "Started" -msgstr "Başladı" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "Bitti" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Keşfet" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "Bilinmeyen Durum" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -801,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:1613 +#: 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 @@ -862,12 +901,13 @@ msgstr "Google Oauth hatası, lütfen tekrar deneyin." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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ş" @@ -883,497 +923,618 @@ 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "eKitaplar" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Son eKitapları göster" -#: cps/render_template.py:44 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:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -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:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Okunmamışları göster" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Keşfet" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Değerlendirmeler" -#: cps/render_template.py:90 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:91 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:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Ara" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Yayınlanma (sonra)" + +#: cps/search.py:195 +msgid "Published before " +msgstr "Yayınlanma (önce)" + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Değerlendirme <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Değerlendirme >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Gelişmiş Arama" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "Geçersiz kitaplık seçildi" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Maalesef bu kitaplığa eKitap eklemenize izin verilmiyor: %(shelfname)s" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "eKitap zaten bu kitaplıkta bulunuyor: %(shelfname)s" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "eKitap kitaplığa eklendi: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "eKitaplar zaten bu kitaplıkta bulunuyor: %(name)s" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "eKitaplar kitaplığa eklendi: %(sname)s" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "eKitaplar kitaplığa eklenemedi: %(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "eKitap kitaplıktan silindi: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Kitaplık oluştur" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Maalesef bu kitaplıktan eKitap silmenize izin verilmiyor: %(sname)s" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Kitaplığı düzenle" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "Metaveri başarıyla güncellendi" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Kitaplık sıralamasını değiştir: '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s kitaplığı oluşturuldu." -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s kitaplığı değiştirildi" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Bir hata oluştu" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "Metaveri başarıyla güncellendi" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Kitaplık sıralamasını değiştir: '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Kitaplık: '%(name)s'" -#: cps/shelf.py:465 +#: 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/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Görevler" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Bekleniyor" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Başarısız" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Başladı" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Bitti" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Bilinmeyen Durum" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" msgstr "Güncelleme bilgileri okunurken beklenmeyen veri" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "Yeni güncelleme mevcut değil. Zaten en son sürüme sahipsiniz." -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "Yeni bir güncelleme mevcut. Son sürüme güncellemek için aşağıdaki düğmeye tıklayın." -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "Güncelleme bilgileri alınamadı" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "Son kararlı sürüme güncellemek için aşağıdaki düğmeye tıklayın." -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "Yeni bir güncelleme mevcut. Son sürüme güncellemek için aşağıdaki düğmeye tıklayın: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "Sürüm bilgisi mevcut değil" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Keşfet (Rastgele)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Yazar: %(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Yayınevi: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Seri: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Değerlendirme: %(rating)s yıldız" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Biçim: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategori: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Dil: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Gelişmiş Arama" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Ara" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Değerlendirme listesi" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "Biçim listesi" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "Görevler" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "Yayınlanma (sonra)" - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Yayınlanma (önce)" - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "Değerlendirme <= %(rating)s" +#: 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:1317 +#: cps/web.py:1240 #, python-format -msgid "Rating >= %(rating)s" -msgstr "Değerlendirme >= %(rating)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:1319 +#: cps/web.py:1243 #, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" +msgid "Oops! There was an error sending book: %(res)s" msgstr "" -#: cps/web.py:1527 -#, 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:1531 -#, python-format -msgid "Oops! There was an error sending this book: %(res)s" +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1533 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/web.py:1550 -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/templates/layout.html:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP Kimlik Doğrulaması etkinleştirilemiyor" -#: cps/web.py:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: 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:1638 +#: 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:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "eKitap-Dönüştürücü hatası: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "metaveri düzenle" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Yükleme" + #: cps/templates/admin.html:9 msgid "Users" msgstr "" @@ -1386,14 +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 -msgid "Send to Kindle E-mail Address" -msgstr "" +#, fuzzy +msgid "Send to eReader Email" +msgstr "E-Posta adresiniz" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Yönetim" @@ -1403,13 +1565,8 @@ msgstr "Yönetim" msgid "Password" msgstr "Şifre" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Yükleme" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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" @@ -1423,7 +1580,7 @@ msgstr "" msgid "Edit" msgstr "Düzenleme" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1434,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 @@ -1464,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 @@ -1536,78 +1689,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "Güncelleme" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Sürüm" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaylar" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Geçerli sürüm" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Güncelle" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "" @@ -1619,39 +1803,39 @@ msgstr "ile" msgid "In Library" msgstr "Kitaplıkta" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "azalt" @@ -1659,165 +1843,166 @@ msgstr "azalt" msgid "More by" msgstr "daha fazla" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "eKitabı Sil" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "Biçimleri Sil:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "Biçime dönüştür:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "Biçimden dönüştür:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "bir seçenek seçin" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "Dönüştür:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "eKitabı dönüştür" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Kitap Adı" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Yazar" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Açıklama" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etiketler" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Değerlendirme" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Yayınevi" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Anahtar Kelime" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr "Anahtar kelime ara" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Forma metaveri yüklemek için kapağa tıklayın" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Yükleniyor..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Kaynak" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Arama hatası!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "" @@ -1910,7 +2095,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1926,6 +2111,7 @@ msgid "Enter " msgstr "Kayıt ol" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 msgid "Are you really sure?" msgstr "Emin misiniz?" @@ -2030,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 @@ -2046,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 @@ -2236,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" @@ -2248,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" @@ -2338,79 +2570,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Okunmadı olarak işaretle" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Okundu olarak işaretle" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Okudum" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Açıklama:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: 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:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2434,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:29 +#: 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" @@ -2463,187 +2698,195 @@ msgstr "Servis adı girin" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: 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-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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Anasayfa" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Hesap" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Çıkış" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Yükleniyor..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Hata" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Yükleme tamamlandı, işleniyor, lütfen bekleyin..." -#: cps/templates/layout.html:76 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 "Ayarlar" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "Hesap" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Çıkış" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Gözat" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Hakkında" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Önceki" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "eKitap Detayları" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "" @@ -2652,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 "" @@ -2748,7 +2991,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Kitap" @@ -2762,128 +3005,162 @@ msgstr "" msgid "epub Reader" msgstr "PDF Okuyucu" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Açık" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Koyu" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Geri" + +#: 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:116 -msgid "Light" -msgstr "Açık" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "Koyu" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Yönetim sayfası" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2892,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" @@ -2911,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 @@ -2930,15 +3207,19 @@ msgstr "" msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Sonuçlar:" @@ -2950,64 +3231,72 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Bu Kitaplığı sil" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3052,7 +3341,7 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" +msgid "Program" msgstr "" #: cps/templates/stats.html:34 @@ -3079,8 +3368,16 @@ msgstr "İlerleme" msgid "Run Time" msgstr "" -#: cps/templates/tasks.html:18 -msgid "Start Time" +#: 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 "" + +#: 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 @@ -3146,17 +3443,17 @@ msgstr "Kullanıcı adı seç" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "E-Posta adresiniz" +msgid "Enter Email" +msgstr "Deneme e-Postası" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "E-Posta adresiniz" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "Deneme e-Postası" #: cps/templates/user_table.html:137 @@ -3220,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 7dd8dec3..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 ae89e56d..dc11c40a 100644 --- a/cps/translations/uk/LC_MESSAGES/messages.po +++ b/cps/translations/uk/LC_MESSAGES/messages.po @@ -6,599 +6,642 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: \n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "Статистика" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Сервер перезавантажено, будь-ласка, перезавантажте сторінку" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Виконується зупинка серверу, будь-ласка, закрийте вікно" -#: cps/admin.py:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" +msgstr "Невідома команда" + +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "Сторінка адміністратора" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Настройки сервера" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Конфігурація інтерфейсу" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Керування сервером" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" -msgstr "" +msgstr "Всі" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" -msgstr "" +msgstr "Користувача не знайдено" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" -msgstr "" +msgstr "{} користувачі видалені успішно" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" -msgstr "" +msgstr "Не правильна роль" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:599 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: 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:607 +#: 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:610 +#: 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:612 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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 "" +msgstr "Заборонити" -#: cps/admin.py:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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 "" +msgstr "Дозволити" -#: cps/admin.py:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Тег не знайдено" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Змінити налаштування SMTP" -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "З'єднання з базою даних закрите" - -#: cps/admin.py:1386 -#, fuzzy -msgid "Database Configuration" -msgstr "Особливі налаштування" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "Будь-ласка, заповніть всі поля!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" +#: 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 "" -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "Додати користувача" - -#: cps/admin.py:1427 +#: cps/admin.py:1323 #, python-format -msgid "User '%(user)s' created" -msgstr "Користувач '%(user)s' додан" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1463 +#: cps/admin.py:1326 #, python-format -msgid "User '%(nick)s' deleted" -msgstr "Користувача '%(nick)s' видалено" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "Змінити користувача %(nick)s" - -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" -msgstr "Користувача '%(nick)s' оновлено" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "Змінити налаштування SMTP" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1633 -#, python-format -msgid "There was an error sending the Test e-mail: %(res)s" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." +#: 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:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1679 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "Змінити користувача %(nick)s" + +#: cps/admin.py:1436 +#, python-format +msgid "Success! Password for user %(user)s reset" msgstr "" -#: cps/admin.py:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Перевірка оновлень" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Завантаження оновлень" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Розпакування оновлення" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" -msgstr "" +msgstr "Заміна файлів" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "З'єднання з базою даних закрите" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" -msgstr "" +msgstr "Сервер зупиняється" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Оновлення встановлені, натисніть ok і перезавантажте сторінку" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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 "" +msgstr "Оновлення неуспішне:" -#: cps/admin.py:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" -msgstr "" +msgstr "HTTP помилка" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" -msgstr "" +msgstr "Помилка зʼєднання" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" -msgstr "" +msgstr "Помилка" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 -msgid "not installed" -msgstr "не встановлено" - -#: cps/converter.py:31 -msgid "Execution permissions missing" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +#: cps/admin.py:1730 +msgid "DB is not Writeable" msgstr "" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "Ні" - -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Неможливо відкрити книгу. Файл не існує або немає доступу." +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "З'єднання з базою даних закрите" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "змінити метадані" +#: cps/admin.py:1879 +#, fuzzy +msgid "Database Configuration" +msgstr "Особливі налаштування" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Будь-ласка, заповніть всі поля!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Додати користувача" + +#: cps/admin.py:1920 #, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "" +msgid "User '%(user)s' created" +msgstr "Користувач '%(user)s' додан" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgid "User '%(nick)s' deleted" +msgstr "Користувача '%(nick)s' видалено" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" msgstr "" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "Завантажувальний файл повинен мати розширення" +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:660 +#: cps/admin.py:2043 #, python-format -msgid "Failed to store file %(file)s." +msgid "User '%(nick)s' updated" +msgstr "Користувача '%(nick)s' оновлено" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "не встановлено" + +#: cps/converter.py:32 +msgid "Execution permissions missing" msgstr "" -#: cps/editbooks.py:683 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "File format %(ext)s added to %(book)s" +msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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 "Ні" + +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "" + +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "Завантажувальний файл повинен мати розширення" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "змінити метадані" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" +msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" +msgid "Failed to create path %(path)s (Permission denied)." msgstr "" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "" + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" msgstr "" #: cps/gdrive.py:58 @@ -614,185 +657,178 @@ msgstr "Домен зворотнього зв'язку не підтвердж 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "Відправити на Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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 "" -#: cps/helper.py:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +msgid "Test Email" msgstr "" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" -msgstr "" +#: 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:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "Відправити на Kindle" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:529 cps/helper.py:538 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "" -#: cps/helper.py:572 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "" -#: cps/helper.py:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "" - -#: cps/helper.py:941 -msgid "Started" -msgstr "" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Огляд" -#: cps/helper.py:943 -msgid "Finished" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" msgstr "" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "" - -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -801,9 +837,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1613 +#: 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 @@ -862,12 +898,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" -msgstr "" +msgstr "{} зірок" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "Ім'я користувача" @@ -883,496 +920,613 @@ msgstr "Час дії токено вичерпано" msgid "Success! Please return to your device" msgstr "Вдалося! Будь-ласка, поверніться до вашого пристрою" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" -msgstr "" +msgstr "Книжки" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Показувати останні книги" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Популярні книги" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Показувати популярні книги" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Книги з найкращим рейтингом" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Показувати прочитані та непрочитані книги" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" -msgstr "" +msgstr "Показати не прочитані" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "Огляд" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" -msgstr "" +msgstr "Видавництва" -#: cps/render_template.py:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" -msgstr "" +msgstr "Рейтинги" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" -msgstr "" +msgstr "Формати файлів" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" -msgstr "" +msgstr "Архівні книжки" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" -msgstr "" +msgstr "Список книжок" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "Пошук" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Опубліковані після " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Опубліковано до " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Рейтинг <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Рейтинг >= %(rating)s" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Розширений пошук" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "" -#: cps/shelf.py:73 +#: cps/shelf.py:55 #, fuzzy msgid "Sorry you are not allowed to add a book to that shelf" msgstr "Вибачте, але у вас немає дозволу для видалення книги з цієї полиці" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "Книга додана на книжкову полицю: %(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "Книга видалена з книжкової полиці: %(sname)s" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "створити книжкову полицю" -#: cps/shelf.py:236 +#: cps/shelf.py:218 #, fuzzy msgid "Sorry you are not allowed to edit this shelf" msgstr "Вибачте, але у вас немає дозволу для видалення книги з цієї полиці" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "Змінити книжкову полицю" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Змінити розташування книжкової полиці '%(name)s'" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Створена книжкова полиця %(title)s" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Книжкова полиця %(title)s змінена" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Сталась помилка" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -msgid "Shelf successfully deleted" -msgstr "" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "Змінити розташування книжкової полиці '%(name)s'" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Книжкова полиця: '%(name)s'" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Помилка при відкриванні полиці. Полиця не існує або до неї відсутній доступ" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Завдання" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Очікує" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Розпочато" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Завершено" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Закінчено" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Відмінено" + +#: 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 "" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Огляд (випадкові книги)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Популярні книги (найбільш завантажувані)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" -msgstr "" +msgstr "Видавництво: %(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Серії: %(serie)s" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Рейтинг: Відсутній" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" -msgstr "" +msgstr "Рейтинг: %(rating)s зірок" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" -msgstr "" +msgstr "Формат файлу: %(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Категорія: %(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Мова: %(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "Розширений пошук" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "Пошук" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" -msgstr "DLS" +msgstr "Завантаження" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" -msgstr "" +msgstr "Список рейтингів" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" -msgstr "" - -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "" - -#: cps/web.py:1293 -msgid "Published before " -msgstr "Опубліковано до" - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "" +msgstr "Список форматів файлу" -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Будь-ласка, спочатку сконфігуруйте параметри SMTP" -#: cps/web.py:1527 +#: 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:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: 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:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Помилка в імені користувача або паролі" -#: cps/web.py:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1644 -msgid "Please enter valid username to reset password" +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." msgstr "" -#: cps/web.py:1651 -#, python-format +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "Помилка в імені користувача або паролі" + +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "" +msgstr "Ви увійшли як користувач: '%(nickname)s'" -#: cps/web.py:1717 cps/web.py:1766 +#: 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:1733 -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:154 -#, python-format -msgid "Calibre ebook-convert %(tool)s not found" +#: 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" +msgstr "" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:275 +msgid "Convert" msgstr "" -#: cps/tasks/convert.py:187 -#, python-format -msgid "%(format)s format not found on disk" +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/convert.py:191 -msgid "Ebook converter failed with unknown error" +#: cps/tasks/mail.py:269 +msgid "E-mail" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "змінити метадані" + +#: cps/tasks/thumbnail.py:96 #, python-format -msgid "Kepubify-converter failed: %(error)s" +msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/convert.py:223 -#, python-format -msgid "Converted file not found or more than one file in folder %(folder)s" +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/convert.py:246 -#, python-format -msgid "Ebook-converter failed: %(error)s" +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/convert.py:269 -#, python-format -msgid "Calibre failed with error: %(error)s" +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Додати нову книгу" + #: cps/templates/admin.html:9 msgid "Users" msgstr "Список користувачів" @@ -1385,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Адмін" @@ -1402,13 +1557,8 @@ msgstr "Адмін" msgid "Password" msgstr "Пароль" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "Додати нову книгу" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "Завантажити" @@ -1422,7 +1572,7 @@ msgstr "" msgid "Edit" msgstr "Редагувати" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1433,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 @@ -1463,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 @@ -1484,7 +1630,7 @@ msgstr "Папка Calibre DB" #: cps/templates/admin.html:113 cps/templates/config_edit.html:68 msgid "Log Level" -msgstr "" +msgstr "Рівень логування" #: cps/templates/admin.html:117 msgid "Port" @@ -1492,7 +1638,7 @@ msgstr "Порт" #: cps/templates/admin.html:122 msgid "External Port" -msgstr "" +msgstr "Зовнішній порт" #: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 msgid "Books per Page" @@ -1535,78 +1681,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 -msgid "Administration" -msgstr "Адміністрування" - #: cps/templates/admin.html:167 -msgid "Download Debug Package" +msgid "Scheduled Tasks" +msgstr "Заплановані завдання" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" -#: cps/templates/admin.html:168 -msgid "View Logs" +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +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 "" -#: cps/templates/admin.html:171 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" -msgstr "Повторне підключення до БД Calibre" +msgstr "" -#: cps/templates/admin.html:172 -msgid "Restart" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:173 -msgid "Shutdown" +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "" -#: cps/templates/admin.html:178 -msgid "Update" +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Адміністрування" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Переглянути логи" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Перезавантажити" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Вимкнути" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Інформація про версію" + +#: cps/templates/admin.html:225 msgid "Version" -msgstr "" +msgstr "Версія" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" -msgstr "" +msgstr "Деталі" -#: cps/templates/admin.html:189 -msgid "Current version" -msgstr "" +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Поточна версія" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Перевірка оновлень" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Встановити оновлення" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" -msgstr "" +msgstr "Впевнені що хочете перезавантажити?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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 "" +msgstr "Скасувати" -#: cps/templates/admin.html:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Встановлення оновлень, будь-ласка, не оновлюйте сторінку" @@ -1618,39 +1795,39 @@ msgstr "через" msgid "In Library" msgstr "У бібліотеці" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "" @@ -1658,165 +1835,166 @@ msgstr "" msgid "More by" msgstr "Більше за" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "Видалити книгу" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" -msgstr "" +msgstr "Видалити формати:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" -msgstr "" +msgstr "Конвертувати з:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" -msgstr "" +msgstr "Конвертувати в:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" -msgstr "" +msgstr "Конвертувати книгу" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "Назва книги" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "Автор" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "Опис" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" -msgstr "" +msgstr "Ідентифікатори" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" -msgstr "" +msgstr "Видалити" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" -msgstr "" +msgstr "Додати ідентифікатор" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Теги" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "Рейтинг" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "Опубліковано" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "Видавець" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "Ні" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "Формат завантаження" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "переглянути книгу після редагування" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "Отримати метадані" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" +msgstr "Зберегти" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "Ключове слово" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " Пошук по ключовому слову" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "Натисніть на обкладинку, щоб отримати метадані" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "Завантаження..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "Закрити" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "Джерело" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "Помилка пошуку!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "" @@ -1893,7 +2071,7 @@ msgstr "" #: cps/templates/book_table.html:71 msgid "Publishing Date" -msgstr "" +msgstr "Дата публікації" #: cps/templates/book_table.html:72 msgid "Enter Publishers" @@ -1901,14 +2079,14 @@ msgstr "" #: cps/templates/book_table.html:73 msgid "Enter comments" -msgstr "" +msgstr "Введіть коментар" #: cps/templates/book_table.html:73 msgid "Comments" -msgstr "" +msgstr "Коментарі" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1924,6 +2102,7 @@ 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 "" @@ -1937,7 +2116,7 @@ msgstr "" #: cps/templates/book_table.html:126 msgid "Merge" -msgstr "" +msgstr "Обʼєднати" #: cps/templates/config_db.html:12 msgid "Location of Calibre Database" @@ -1985,19 +2164,19 @@ msgstr "Розташування ключових слів SSL (залиште #: cps/templates/config_edit.html:43 msgid "Update Channel" -msgstr "" +msgstr "Канал оновлення" #: cps/templates/config_edit.html:45 msgid "Stable" -msgstr "" +msgstr "Стабільний" #: cps/templates/config_edit.html:46 msgid "Nightly" -msgstr "" +msgstr "Нічний" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "" +msgstr "Довірені хости (розділені комою)" #: cps/templates/config_edit.html:61 msgid "Logfile Configuration" @@ -2028,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 @@ -2044,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 @@ -2085,7 +2264,7 @@ msgstr "" #: cps/templates/config_edit.html:180 msgid "Login type" -msgstr "" +msgstr "Тип логіну" #: cps/templates/config_edit.html:182 msgid "Use Standard Authentication" @@ -2113,11 +2292,11 @@ msgstr "" #: cps/templates/config_edit.html:205 msgid "TLS" -msgstr "" +msgstr "TLS" #: cps/templates/config_edit.html:206 msgid "SSL" -msgstr "" +msgstr "SSL" #: cps/templates/config_edit.html:210 msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" @@ -2137,7 +2316,7 @@ msgstr "" #: cps/templates/config_edit.html:235 msgid "Anonymous" -msgstr "" +msgstr "Анонім" #: cps/templates/config_edit.html:236 msgid "Unauthenticated" @@ -2189,7 +2368,7 @@ msgstr "" #: cps/templates/config_edit.html:280 msgid "Autodetect" -msgstr "" +msgstr "Автовизначення" #: cps/templates/config_edit.html:281 msgid "Custom Filter" @@ -2234,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 "Переглянути налаштування" @@ -2246,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 "Тема" @@ -2337,79 +2562,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Відкрити в браузері" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" -msgstr "" +msgstr "Прослухати в браузері" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" -msgstr "" +msgstr "Опубліковано" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" -msgstr "" +msgstr "Відмітити як не прочитане" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" -msgstr "" +msgstr "Відмітити як прочитане" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Прочитано" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" -msgstr "" +msgstr "Відновити з архіву" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" -msgstr "" +msgstr "Додати в архів" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" -msgstr "" +msgstr "Заархівовано" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Опис:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Додати на книжкову полицю" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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 "" +msgstr "(Публічно)" -#: cps/templates/detail.html:298 +#: 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 @@ -2430,13 +2657,14 @@ msgstr "Пароль SMTP" #: cps/templates/email_edit.html:58 msgid "Attachment Size Limit" -msgstr "" +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:29 +#: 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 "Назад" @@ -2447,201 +2675,209 @@ msgstr "" #: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 msgid "Add Domain" -msgstr "" +msgstr "Додати домен" #: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 #: cps/templates/user_table.html:27 msgid "Add" -msgstr "" +msgstr "Додати" #: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 msgid "Enter domainname" -msgstr "" +msgstr "Введіть домен" #: cps/templates/email_edit.html:92 msgid "Denied Domains (Blacklist)" -msgstr "" +msgstr "Заборонені домени (Чорний список)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Список" + +#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Включити навігацію" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "Завантаження..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" -msgstr "" +msgstr "Помилка" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "" -#: cps/templates/layout.html:76 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 "Налаштування" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "Вийти" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Перегляд" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Про програму" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Попередній перегляд" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Деталі" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "Запам'ятати мене" @@ -2650,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" @@ -2696,7 +2932,7 @@ msgstr "" #: cps/templates/modal_dialogs.html:15 msgid "Enter Tag" -msgstr "" +msgstr "Введіть тег" #: cps/templates/modal_dialogs.html:24 msgid "Add View Restriction" @@ -2724,7 +2960,7 @@ msgstr "" #: cps/templates/modal_dialogs.html:76 msgid "Choose File Location" -msgstr "" +msgstr "Оберіть розташування файлу" #: cps/templates/modal_dialogs.html:82 msgid "type" @@ -2746,7 +2982,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 #, fuzzy msgid "Ok" msgstr "Книга" @@ -2759,135 +2995,169 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "Назад" + +#: 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:116 -msgid "Light" +#: cps/templates/readcbr.html:110 +msgid "Display" msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Сторінка адміністратора" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" msgstr "" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" -msgstr "" +msgstr "Краще" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" -msgstr "" +msgstr "Ширина" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" -msgstr "" +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 "" +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 "" +msgstr "Вертикально" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" -msgstr "" +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 "" +msgstr "Показати" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" -msgstr "" +msgstr "Сховати" #: cps/templates/readdjvu.html:5 msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -2905,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 @@ -2924,15 +3194,19 @@ msgstr "Після цього ви автоматично ввійдете в с msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "Результати для:" @@ -2944,64 +3218,72 @@ 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 "" +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 "" +msgstr "Від:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" -msgstr "" +msgstr "До:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "Видалити цю книжкову полицю" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3043,11 +3325,11 @@ msgstr "Серій в цій бібліотеці" #: cps/templates/stats.html:29 msgid "System Statistics" -msgstr "" +msgstr "Статистика системи" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "Назва" +msgid "Program" +msgstr "Програма" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3055,31 +3337,39 @@ msgstr "Встановлена версія" #: cps/templates/tasks.html:12 msgid "User" -msgstr "" +msgstr "Користувач" #: cps/templates/tasks.html:14 msgid "Task" -msgstr "" +msgstr "Завдання" #: cps/templates/tasks.html:15 msgid "Status" -msgstr "" +msgstr "Статус" #: cps/templates/tasks.html:16 msgid "Progress" -msgstr "" +msgstr "Прогрес" #: cps/templates/tasks.html:17 msgid "Run 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 "" -#: cps/templates/tasks.html:18 -msgid "Start Time" +#: 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 "" +msgstr "Скинути пароль користувача" #: cps/templates/user_edit.html:43 msgid "Language of Books" @@ -3087,7 +3377,7 @@ msgstr "Показувати книги на мовах" #: cps/templates/user_edit.html:54 msgid "OAuth Settings" -msgstr "" +msgstr "Налаштування OAuth" #: cps/templates/user_edit.html:56 msgid "Link" @@ -3103,7 +3393,7 @@ msgstr "" #: cps/templates/user_edit.html:66 msgid "Create/View" -msgstr "" +msgstr "Створити/Переглянути" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" @@ -3127,7 +3417,7 @@ msgstr "" #: cps/templates/user_table.html:80 cps/templates/user_table.html:103 msgid "Select..." -msgstr "" +msgstr "Обрати..." #: cps/templates/user_table.html:131 #, fuzzy @@ -3141,21 +3431,22 @@ 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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "Kindle" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "" +#, fuzzy +msgid "eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:137 msgid "Locale" -msgstr "" +msgstr "Локалізація" #: cps/templates/user_table.html:138 msgid "Visible Book Languages" @@ -3167,15 +3458,15 @@ msgstr "" #: cps/templates/user_table.html:139 msgid "Allowed Tags" -msgstr "" +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" @@ -3200,7 +3491,7 @@ msgstr "Дозволити зміну пароля" #: cps/templates/user_table.html:147 msgid "View" -msgstr "" +msgstr "Показати" #: cps/templates/user_table.html:150 #, fuzzy @@ -3213,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 new file mode 100644 index 00000000..5c9e3270 Binary files /dev/null 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 new file mode 100644 index 00000000..59f95fb6 --- /dev/null +++ b/cps/translations/vi/LC_MESSAGES/messages.po @@ -0,0 +1,3502 @@ +# This file is distributed under the same license as the Calibre-web project +# Ha Link +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: 2022-09-20 21:36+0700\n" +"Last-Translator: Ha Link \n" +"Language: vi\n" +"Language-Team: \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 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 "Thống kê" + +#: 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: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: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:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "" + +#: 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:231 +msgid "Admin page" +msgstr "Trang admin" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Thiết lập cơ bản" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "Thiết lập UI" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Chỉnh sửa người dùng" + +#: 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:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Không tìm thấy user" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "{} người dung đã đươc xoá thành công" + +#: 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:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Yêu cầu không đúng định dạng" + +#: 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:482 +msgid "Guest can't have this role" +msgstr "Khách không thể mang vai trò này" + +#: 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: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:500 +msgid "Invalid role" +msgstr "Vai trò không hợp lệ" + +#: 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:514 +msgid "Invalid view" +msgstr "View không hợp lệ" + +#: 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:521 +msgid "No Valid Locale Given" +msgstr "Địa chỉ cung cấp không hợp lệ" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Ngôn ngữ sách không hợp lệ" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Tham số không tồn tại" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Cột đọc không hợp lệ" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Cột bị hạn chế không hợp lệ" + +#: 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: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: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: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: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: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: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: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: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: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: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: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:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "" + +#: 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: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: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:921 +msgid "{} sync entries deleted" +msgstr "{} mục nhập đồng bộ hóa đã bị xóa" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Tag không tồn tại" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Hành động không hợp lệ" + +#: cps/admin.py:1111 +msgid "client_secrets.json Is Not Configured For Web Application" +msgstr "" + +#: 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:1162 +msgid "Access Logfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1196 +msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" +msgstr "" + +#: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "" + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "" + +#: cps/admin.py:1225 +#, python-format +msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" +msgstr "" + +#: cps/admin.py:1227 +msgid "LDAP Member User Filter Has Unmatched Parenthesis" +msgstr "" + +#: cps/admin.py:1234 +msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: 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:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "" + +#: 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 "Lỗi cơ sở dữ liệu: %(error)s." + +#: 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:1326 +#, python-format +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "" + +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "" + +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "" + +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: 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: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:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: 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:1436 +#, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "" + +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." +msgstr "" + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "Đang giải nén tệp cập nhật" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "They thế tập tin" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "Liên kết cơ sở dữ liệu đã được đóng" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "Đang dừng server" + +#: 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: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:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +msgid "HTTP Error" +msgstr "Lỗi HTTP" + +#: 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:1528 cps/updater.py:393 cps/updater.py:630 +msgid "Timeout while establishing connection" +msgstr "" + +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Lỗi chung" + +#: 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:1531 +msgid "Files could not be replaced during update" +msgstr "" + +#: cps/admin.py:1555 +msgid "Failed to extract at least One LDAP User" +msgstr "" + +#: cps/admin.py:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "" + +#: cps/admin.py:1613 +#, python-format +msgid "Error: %(ldaperror)s" +msgstr "" + +#: cps/admin.py:1617 +msgid "Error: No user returned in response of LDAP server" +msgstr "" + +#: cps/admin.py:1650 +msgid "At Least One LDAP User Not Found in Database" +msgstr "" + +#: cps/admin.py:1652 +msgid "{} User Successfully Imported" +msgstr "" + +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "" + +#: 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:1879 +msgid "Database Configuration" +msgstr "Thiết lập cơ sở dữ lieu :)))" + +#: 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:1903 +msgid "E-mail is not from valid domain" +msgstr "Địa chỉ email không hợp lệ" + +#: 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: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:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Người dùng '%(nick)s' đã bị xoá" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Không thể xoá người dùng khách" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +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:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Người dùng '%(nick)s' đã được cập nhật" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "chưa cài đặt" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "" + +#: 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: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 "None" + +#: 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:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" +msgstr "" + +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +msgstr "" + +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadata đã được cập nhật thành công" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "File %(file)s đã được tải lên" + +#: 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:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "" + +#: 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:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "" + +#: 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: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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "" + +#: cps/editbooks.py:753 +#, python-format +msgid "File %(filename)s could not saved to temp dir" +msgstr "" + +#: cps/editbooks.py:773 +#, python-format +msgid "Failed to Move Cover File %(file)s: %(error)s" +msgstr "" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "" + +#: cps/editbooks.py:992 +#, python-format +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" + +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "" + +#: 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:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "" + +#: cps/gdrive.py:95 +msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" +msgstr "" + +#: cps/helper.py:81 +#, python-format +msgid "%(format)s format not found for book id: %(book)d" +msgstr "" + +#: 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:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s không tìm thấy: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" +msgstr "Gửi tới Kindle" + +#: 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:115 +#, fuzzy +msgid "Calibre-Web Test Email" +msgstr "Calibre-Web test e-mail" + +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" +msgstr "Test e-mail" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Bắt đầu với Calibre-Web" + +#: 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:149 cps/helper.py:155 +#, fuzzy, python-format +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:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" +msgstr "Gửi %(format)s tới Kindle" + +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "%(book)s gửi tới Kindle" + +#: 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:342 +msgid "Read status could not set: {}" +msgstr "" + +#: 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: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:382 +#, python-format +msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" +msgstr "" + +#: cps/helper.py:447 +#, python-format +msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "" + +#: 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:562 +#, python-format +msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "" + +#: cps/helper.py:582 +msgid "Error in rename file in path: {}" +msgstr "" + +#: 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:665 +msgid "Found an existing account for this Email address" +msgstr "" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Username này đã bị sử dụng" + +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "Định dạng email address không hợp lệ" + +#: 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:862 +msgid "Error Downloading Cover" +msgstr "Lỗi tải xuống ảnh bìa" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Định dạng ảnh bìa lỗi" + +#: cps/helper.py:868 +msgid "You are not allowed to access localhost or the local network for cover uploads" +msgstr "" + +#: 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:894 +msgid "Cover-file is not a valid image file, or could not be stored" +msgstr "" + +#: cps/helper.py:905 +msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" +msgstr "" + +#: cps/helper.py:917 +msgid "Invalid cover file content" +msgstr "" + +#: cps/helper.py:921 +msgid "Only jpg/jpeg files are supported as coverfile" +msgstr "" + +#: cps/helper.py:973 +msgid "Unrar binary file not found" +msgstr "" + +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "" + +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Khám phá" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" + +#: 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:116 +msgid "Kobo Setup" +msgstr "Thiết lập Kobo" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Đăng nhập với Github thất bại." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Lấy thông tin user từ Github thất bại." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Đăng nhập với Google thất bại." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Lấy thông tin người dùng từ Google thất bại." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "Oauth Github lỗi, xin thử lại sau." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "Github Oauth lỗi: {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Google Oauth lỗi, làm ơn thử lại sau." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Google Oauth lỗi: {}" + +#: cps/opds.py:274 +msgid "{} Stars" +msgstr "{} sao" + +#: 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" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Không tìm thấy token" + +#: cps/remotelogin.py:83 cps/remotelogin.py:116 +msgid "Token has expired" +msgstr "Token đã hết hạn" + +#: cps/remotelogin.py:92 +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:42 cps/web.py:414 +msgid "Books" +msgstr "Sách" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Hiển thị sách gần đây" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Sách hot" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Hiển thị sách hot" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Sách đã tải" + +#: 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: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: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: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:64 +#, fuzzy +msgid "Show Read and Unread" +msgstr "Hiển thị đã đọc và chưa đọc" + +#: 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:68 +msgid "Show unread" +msgstr "Hiện thị sách chưa đọc" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Khám phá" + +#: 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:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 +msgid "Categories" +msgstr "Chủ đề" + +#: 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: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:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Hiển thị chọn series" + +#: 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: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: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: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: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: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:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Đánh giá" + +#: 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:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Định dạng file" + +#: 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:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Sách đã lưu trữ" + +#: 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:101 cps/web.py:807 +msgid "Books List" +msgstr "Danh sách sách" + +#: 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: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 "Tìm kiếm" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Phát hành sau " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Phát hành trước " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Đánh giá <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Đánh giá >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Trạng thái đọc = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Tìm kiếm nâng cao" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Xin lỗi bạn không có quyền thêm sách vào giá đó" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "Sách đã được thêm vào giá: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "Sách đã được xoá khỏi giá: %(sname)s" + +#: cps/shelf.py:200 +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:157 +msgid "Create a Shelf" +msgstr "Tạo một giá sách" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Xin lỗi bạn không có quyền chỉnh sửa giá sách này" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Chỉnh sửa giá sách" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "" + +#: 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:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Giá sách %(title)s đã được tạo" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Giá sách %(title)s đã được thay đổi" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "Có lỗi xảy ra" + +#: cps/shelf.py:372 +#, python-format +msgid "A public shelf with the name '%(title)s' already exists." +msgstr "" + +#: cps/shelf.py:383 +#, python-format +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "" + +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "" + +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "" + +#: 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:62 +msgid "Waiting" +msgstr "Đang chờ" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Thất bại" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Đã bắt đầu" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Đã hoàn thành" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +#, fuzzy +msgid "Cancelled" +msgstr "Huỷ bỏ" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Trạng thái không xác định" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "" + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "" + +#: 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 "" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "" + +#: cps/web.py:620 +#, fuzzy +msgid "Rating: None" +msgstr "Đánh giá cao hơn" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Tải xuống" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Danh sách đánh giá" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Danh sách định dạng file" + +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "" + +#: cps/web.py:1240 +#, python-format +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" +msgstr "" + +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "" + +#: 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 "Đăng ký" + +#: 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 "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: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:1388 +#, fuzzy, python-format +msgid "Could not login: %(message)s" +msgstr "Không thể đăng nhập: %(message)s" + +#: 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: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: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: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:1471 cps/web.py:1521 +#, python-format +msgid "%(name)s's Profile" +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" +msgstr "" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "" + +#: cps/tasks/convert.py:275 +#, fuzzy +msgid "Convert" +msgstr "Khám phá" + +#: cps/tasks/database.py:28 +#, fuzzy +msgid "Reconnecting Calibre database" +msgstr "Kết nối lại với cơ sở dữ liệu Calibre" + +#: cps/tasks/mail.py:269 +#, fuzzy +msgid "E-mail" +msgstr "Test e-mail" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Tải lên" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Người dùng" + +#: 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 "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 "Email" +msgstr "Địa chỉ email" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +#, fuzzy +msgid "Send to eReader Email" +msgstr "Kindle" + +#: 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 "Mật khẩu" + +#: 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" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Xem sách" + +#: cps/templates/admin.html:24 cps/templates/user_table.html:131 +#: cps/templates/user_table.html:148 +msgid "Edit" +msgstr "Chỉnh sửa" + +#: 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 "Xoá" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Giá công khai" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "" + +#: cps/templates/admin.html:62 +msgid "Email Server Settings" +msgstr "Thiết lập máy chủ email" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "SMTP Hostname" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "Cổng SMTP" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "SSL" + +#: cps/templates/admin.html:79 cps/templates/email_edit.html:47 +msgid "SMTP Login" +msgstr "Đăng nhập SMTP" + +#: cps/templates/admin.html:83 cps/templates/admin.html:94 +#: cps/templates/email_edit.html:55 +msgid "From Email" +msgstr "Từ E-mail" + +#: cps/templates/admin.html:90 +#, fuzzy +msgid "Email Service" +msgstr "Dịch vụ E-Mail" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "Gmail via Oauth2" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Thiết lập" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Thư mục cơ sở dữ liệu 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 "Cổng" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Sách mỗi trang" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Tải lên" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Ẩn danh" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Đăng ký công khai" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Đăng nhập bằng Magic Link" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Chỉnh sửa thiết lập cơ sở dữ liệu Calibre" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Chỉnh sửa thiết lập cơ bản" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Chỉnh sửa thiết lập UI" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +#, fuzzy +msgid "Reconnect Calibre Database" +msgstr "Kết nối lại với cơ sở dữ liệu Calibre" + +#: 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:212 +msgid "Shutdown" +msgstr "Tắt" + +#: cps/templates/admin.html:221 +#, fuzzy +msgid "Version Information" +msgstr "Thiết lập máy chủ" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Phiên bản" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Chi tiết" + +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Phiên bản hiện tại" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Kiểm tra cập nhật" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Bắt đầu cập nhật" + +#: 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: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 "Huỷ bỏ" + +#: 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:283 +msgid "Updating, please do not reload this page" +msgstr "Đang update, làm ơn đừng load lại trang này" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "via" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "Trong thư viện" + +#: 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 "" + +#: 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 "" + +#: 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 "" + +#: 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 "" + +#: 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 "" + +#: 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 "" + +#: 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 "" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Cùng tác giả" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Xoá sách" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Xoá định dạng:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "Chuyển đổi định dạng sách:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Chuyển đổi từ:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "chọn một lựa chọn" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Chuyển đổi tới:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Chuyển đổi sách" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Tên sách" + +#: 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 "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:154 +msgid "Description" +msgstr "Mô tả" + +#: cps/templates/book_edit.html:73 +msgid "Identifiers" +msgstr "Nhận diện" + +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +msgid "Identifier Type" +msgstr "Kiểu nhận diện" + +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +msgid "Identifier Value" +msgstr "Giá trị nhận diện" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Xoá" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Thêm nhận diện" + +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 +msgid "Tags" +msgstr "Đánh dấu" + +#: cps/templates/book_edit.html:95 +msgid "Series ID" +msgstr "Series ID" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Đánh giá" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Lấy ảnh bìa từ URL (ảnh JPEG sẽ được tải xuống và lưu trong cơ sở dữ liệu)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Tải ảnh bìa từ ổ cứng" + +#: cps/templates/book_edit.html:113 +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: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: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:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Có" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Không" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Định dạng tải lên" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Xem sách sau khi lưu" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Fetch 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 "Lưu" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Từ khoá" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Tìm kiếm từ khoá" + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Ấn vào ảnh cover để tải metadata vào form" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "Đang tải..." + +#: 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" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Nguồn" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Tìm kiếm lỗi!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Không tìm thấy kết quả! Hãy thử lại với từ khoá khác." + +#: 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 "Đây là trường bắt buộc" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Gộp những sách đã chọn" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Bỏ chọn" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Đổi tác giả và tên sách" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Cập nhật sắp xếp theo tên tự động" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Cập nhật sắp xếp theo tác giả tự động" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Nhập tên sách" + +#: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 +#: cps/templates/shelf_edit.html:8 +msgid "Title" +msgstr "Tên" + +#: cps/templates/book_table.html:64 +msgid "Enter Title Sort" +msgstr "Nhập tên sách để sắp xếp" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Tên sắp xếp" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Nhập tác giả sắp xếp" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Tên tác giả sắp xếp" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Nhập tên tác giả" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Nhập thể loại" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Nhập tên series" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Chỉ số series" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Nhập ngôn ngữ" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Ngày phát hành" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Nhập tên nhà phát hành" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Nhập nhận xét" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Nhận xét" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Read 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 "Nhập " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "Bạn có thực sự chắc chắn?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Trộn" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Vị trí cơ sở dữ liệu của Calibre" + +#: cps/templates/config_db.html:22 +msgid "Use Google Drive?" +msgstr "Dùng Google Drive?" + +#: cps/templates/config_db.html:27 +msgid "Authenticate Google Drive" +msgstr "Xác thực Google Drive" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Thư mục Calibre trên Google Drive" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "" + +#: cps/templates/config_db.html:43 +msgid "Revoke" +msgstr "Thu hồi" + +#: cps/templates/config_db.html:68 +msgid "New db location is invalid, please enter valid path" +msgstr "Đường dẫn DB mới không hợp lệ, xin hãy nhập đường dẫn hợp lệ" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Thiết lập máy chủ" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Cổng máy chủ" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "" + +#: cps/templates/config_edit.html:108 +msgid "(Please ensure that users also have upload permissions)" +msgstr "" + +#: cps/templates/config_edit.html:112 +msgid "Allowed Upload Fileformats" +msgstr "" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "" + +#: cps/templates/config_edit.html:127 +msgid "Use Email as Username" +msgstr "" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Sử dụng Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Tạo API Key" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Goodreads API Key" + +#: 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 "" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Kiểu đăng nhập" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "" + +#: cps/templates/config_edit.html:187 +msgid "Use OAuth" +msgstr "" + +#: cps/templates/config_edit.html:194 +msgid "LDAP Server Host Name or IP Address" +msgstr "" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "" + +#: cps/templates/config_edit.html:205 +msgid "TLS" +msgstr "" + +#: cps/templates/config_edit.html:206 +msgid "SSL" +msgstr "" + +#: cps/templates/config_edit.html:210 +msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" +msgstr "" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "" + +#: cps/templates/config_edit.html:262 +msgid "LDAP Server is OpenLDAP?" +msgstr "" + +#: cps/templates/config_edit.html:264 +msgid "Following Settings are Needed For User Import" +msgstr "" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "" + +#: 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 +msgid "External binaries" +msgstr "" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "" + +#: 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 "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 "" + +#: 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 "Chủ đề mặc định" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "calibur! Theme tối" + +#: 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 +msgid "Admin User" +msgstr "Người dùng quản trị" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +msgid "Allow Downloads" +msgstr "Cho phép tải xuống" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "Cho phép xem eBook" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +msgid "Allow Uploads" +msgstr "Cho phép tải lên" + +#: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 +msgid "Allow Edit" +msgstr "Cho phép chỉnh sửa" + +#: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 +msgid "Allow Delete Books" +msgstr "Cho phép xoá sách" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "Cho phép thay đổi mật khẩu" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "Cho phép chỉnh sửa giá sách công khai" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "Ngôn ngữ mặc định" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "Ngôn ngữ hiển thị mặc định của sách" + +#: 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 "Hiển thị sách ngẫu nhiên trong màn hình chi tiết" + +#: 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 "Thêm cho phép/từ chối giá trị cột tuỳ biến" + +#: 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:100 cps/templates/detail.html:120 +msgid "Listen in Browser" +msgstr "Nghe trên trình duyệt" + +#: 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:201 cps/templates/listenmp3.html:111 +msgid "Published" +msgstr "Đã phát hành" + +#: 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:251 cps/templates/listenmp3.html:158 +msgid "Mark As Read" +msgstr "Đánh dấu đã đọc" + +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 +msgid "Read" +msgstr "Đọc" + +#: 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:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "Thêm vào lưu trữ" + +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 +msgid "Archived" +msgstr "Lưu trữ" + +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 +msgid "Description:" +msgstr "Mô tả:" + +#: 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: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:339 +msgid "Edit Metadata" +msgstr "Chỉnh sửa Metadata" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "Chọn kiểu server" + +#: cps/templates/email_edit.html:15 +#, fuzzy +msgid "Standard Email Account" +msgstr "Dùng tài khoản email tiêu chuẩn" + +#: cps/templates/email_edit.html:16 +#, fuzzy +msgid "Gmail Account" +msgstr "Chọn kiểu server" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "Thu hồi quyền truy cập 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 "Mật khẩu SMTP" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "Giới hạn kích thước file đính kèm" + +#: cps/templates/email_edit.html:66 +#, 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:26 +#: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 +msgid "Back" +msgstr "Quay lại" + +#: cps/templates/email_edit.html:74 +msgid "Allowed Domains (Whitelist)" +msgstr "Domains được chấp nhận (Whitelist)" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "Thêm domain" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "Thêm" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +msgid "Enter domainname" +msgstr "Nhập tên domain" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "Domain bị từ chối (Blacklist)" + +#: 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/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "" + +#: cps/templates/generate_kobo_auth_url.html:11 +#, fuzzy +msgid "Kobo Token:" +msgstr "Token đồng bộ Kobo" + +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: cps/templates/http_error.html:34 +msgid "Calibre-Web Instance is unconfigured, please contact your administrator" +msgstr "" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "Quay về trang chủ" + +#: 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 +msgid "Sort authors in alphabetical order" +msgstr "" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 +msgid "Sort authors in reverse alphabetical order" +msgstr "" + +#: 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 +msgid "Start" +msgstr "Bắt đầu" + +#: 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 +msgid "Recently added Books" +msgstr "Sách mới được thêm gần đây" + +#: cps/templates/index.xml:44 +msgid "The latest Books" +msgstr "Sách mới nhất" + +#: cps/templates/index.xml:47 +msgid "Random Books" +msgstr "Sách ngẫu nhiên" + +#: 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:81 +msgid "Books ordered by publisher" +msgstr "Sách sắp xếp theo nhà phát hành" + +#: 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:95 +msgid "Books ordered by series" +msgstr "Sách sắp xếp theo series" + +#: 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:109 +msgid "Books ordered by Rating" +msgstr "Sách sắp xếp theo xếp hạng" + +#: 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:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "Giá sách" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "Sách tổ chức theo giá sách" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "Trang chủ" + +#: cps/templates/layout.html:32 +msgid "Toggle Navigation" +msgstr "" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "Tìm kiếm thư viện" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Tài khoản" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Đăng xuất" + +#: 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:145 +msgid "Browse" +msgstr "Tìm kiếm" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "About" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "Trước" + +#: cps/templates/layout.html:199 +msgid "Book Details" +msgstr "Chi tiết sách" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "Ghi nhớ tôi" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "Quên mật khẩu?" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "Đăng nhập với Magic Link" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "Hiển thị Calibre-Web Log: " + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "Calibre-Web Log: " + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "Hiển thị log truy cập: " + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "Tải xuống Calibre-Web Log" + +#: cps/templates/logviewer.html:21 +msgid "Download Access Log" +msgstr "Tải xuống log truy cập" + +#: 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 +msgid "Enter Tag" +msgstr "Nhập Tag" + +#: 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 "Chọn file location" + +#: cps/templates/modal_dialogs.html:82 +msgid "type" +msgstr "kiểu" + +#: cps/templates/modal_dialogs.html:83 +msgid "name" +msgstr "tên" + +#: cps/templates/modal_dialogs.html:84 +msgid "size" +msgstr "kích thước" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "Thư mục cha" + +#: cps/templates/modal_dialogs.html:98 +msgid "Select" +msgstr "Chọn" + +#: 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 "" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "trình đọc epub" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Sáng" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Tối" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +#, fuzzy +msgid "Black" +msgstr "Quay lại" + +#: 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 "Trình đọc truyện tranh" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "Phím tắt" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "Trang trước" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +msgid "Next Page" +msgstr "Trang tiếp theo" + +#: 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 "Xoay phải" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "Xoay trái" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "Lật ảnh" + +#: 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:122 +msgid "Best" +msgstr "Tốt nhất" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "Rộng" + +#: cps/templates/readcbr.html:124 +msgid "Height" +msgstr "Cao" + +#: cps/templates/readcbr.html:125 +msgid "Native" +msgstr "" + +#: cps/templates/readcbr.html:130 +msgid "Rotate" +msgstr "Xoay" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "Lật" + +#: cps/templates/readcbr.html:144 +msgid "Horizontal" +msgstr "Ngang" + +#: cps/templates/readcbr.html:145 +msgid "Vertical" +msgstr "Dọc" + +#: cps/templates/readcbr.html:150 +msgid "Direction" +msgstr "Hướng" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "Trái sang phải" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "Phải sang trái" + +#: 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 "Thanh cuộn" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "Hiện" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "Ẩn" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "Trình đọc DJVU" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "Trình đọc PDF" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "trình đọc txt" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "Đăng ký tải khoản mới" + +#: cps/templates/register.html:10 +msgid "Choose a username" +msgstr "Chọn tên người dùng" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "Địa chỉ email của bạn" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "Magic Link - Xác thực thiết bị mới" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "Trên thiết bị khác, đăng nhập và thăm quan:" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "Một khi xác nhận, bạn sẽ tự động đăng nhập trên thiết bị này." + +#: cps/templates/remote_login.html:14 +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:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "Không tìm thấy kết quả" + +#: cps/templates/search.html:7 +msgid "Search Term:" +msgstr "Từ khoá tìm kiếm:" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "Kết quả cho:" + +#: cps/templates/search_form.html:21 +msgid "Published Date From" +msgstr "Ngày phát hành từ" + +#: cps/templates/search_form.html:31 +msgid "Published Date To" +msgstr "Ngày phát hành tới" + +#: 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 +msgid "Exclude Languages" +msgstr "" + +#: 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 +msgid "Rating Above" +msgstr "Đánh giá cao hơn" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "Đánh giá thấp hơn" + +#: cps/templates/search_form.html:181 +msgid "From:" +msgstr "Từ:" + +#: cps/templates/search_form.html:191 +msgid "To:" +msgstr "Tới:" + +#: cps/templates/shelf.html:13 +msgid "Delete this Shelf" +msgstr "Xoá giá sách này" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "Chỉnh sửa thông tin giá sách" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "Sắp xếp sách bằng tay" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "Khoá thay đổi thứ tự" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "Mở thay đổi thứ tự" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "Chia sửa với tất cả" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "Đồng bộ giá sách này với thiết bị Kobo" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "Kéo để thay đổi lại thứ tự" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "Sách ẩn" + +#: cps/templates/stats.html:7 +msgid "Library Statistics" +msgstr "Thống kê thư viện" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "Sách trong thư viện" + +#: cps/templates/stats.html:16 +msgid "Authors in this Library" +msgstr "Các tác giả trong thư viện" + +#: cps/templates/stats.html:20 +msgid "Categories in this Library" +msgstr "Các thể loại trong thư viện" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "Các series trong thư viện" + +#: cps/templates/stats.html:29 +msgid "System Statistics" +msgstr "Thống kê hệ thống" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "" + +#: cps/templates/stats.html:34 +msgid "Installed Version" +msgstr "Phiên bản đã cài đặt" + +#: cps/templates/tasks.html:12 +msgid "User" +msgstr "Người dùng" + +#: cps/templates/tasks.html:14 +msgid "Task" +msgstr "Nhiệm vụ" + +#: cps/templates/tasks.html:15 +msgid "Status" +msgstr "Trạng thái" + +#: cps/templates/tasks.html:16 +msgid "Progress" +msgstr "Tiến độ" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "Thời gian chạy" + +#: cps/templates/tasks.html:20 +#, fuzzy +msgid "Actions" +msgstr "Đánh giá" + +#: 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 "Reset mật khẩu người dùng" + +#: cps/templates/user_edit.html:43 +msgid "Language of Books" +msgstr "Ngôn ngữ của sách" + +#: cps/templates/user_edit.html:54 +msgid "OAuth Settings" +msgstr "Thiết lập OAuth" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "Link" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "Unlink" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "Token đồng bộ Kobo" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "Tạo/xem" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "Ép đồng bộ tất cả với Kobo" + +#: 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 "Đồng bộ sách trên những giá được chọn với Kobo" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +msgid "Delete User" +msgstr "Xoá người dùng" + +#: 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 "Chọn..." + +#: cps/templates/user_table.html:131 +msgid "Edit User" +msgstr "Chỉnh sửa người dùng" + +#: cps/templates/user_table.html:134 +msgid "Enter Username" +msgstr "Nhập tên người dùng" + +#: cps/templates/user_table.html:135 +#, fuzzy +msgid "Enter Email" +msgstr "Test e-mail" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "Enter eReader Email" +msgstr "Kindle" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "eReader Email" +msgstr "Test e-mail" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "Ngôn ngữ" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "Những ngôn ngữ hiển thị cho sách" + +#: cps/templates/user_table.html:139 +msgid "Edit Allowed Tags" +msgstr "Chỉnh sửa những tags đươc cho phép" + +#: cps/templates/user_table.html:139 +msgid "Allowed Tags" +msgstr "Tags được cho phép" + +#: cps/templates/user_table.html:140 +msgid "Edit Denied Tags" +msgstr "Chỉnh sửa những tags bị từ chối" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "Tags bị từ chối" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "Chỉnh sửa những giá trị cột được cho phép" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "Giá trị cột được cho phép" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "Chỉnh sửa những cột giá trị bị từ chối" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "Những cột giá trị bị từ chối" + +#: cps/templates/user_table.html:144 +msgid "Change Password" +msgstr "Đổi mật khẩu" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "Xem" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "Chỉnh sửa giá sách công khai" + +#: cps/templates/user_table.html:152 +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 +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Hiển thị đã đọc và chưa đọc" + diff --git a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo index a771e299..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 2cd0a4ca..dff01166 100644 --- a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po +++ b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po @@ -7,786 +7,817 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: zh_Hans_CN \n" -"Plural-Forms: nplurals=1; plural=0\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "统计" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." msgstr "服务器已重启,请刷新页面" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." msgstr "正在关闭服务器,请关闭窗口" -#: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "重新连接成功" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "数据库重新连接成功" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "未知命令" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "成功!书籍已排队进行元数据备份,请检查任务列表以获取结果" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理页" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本配置" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "界面配置" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "管理用户" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "全部" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "找不到用户" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "成功删除 {} 个用户" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "格式错误的请求" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "访客名称无法更改" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "游客无法拥有此角色" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" -msgstr "理员账户不存在,无法删除管理员角色" +msgstr "没有其余管理员账户,无法删除管理员角色" -#: cps/admin.py:464 cps/admin.py:478 +#: 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:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "无效角色" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" -msgstr "游客无法拥有此视图" +msgstr "游客无法查看此页面" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "无效视图" +msgstr "无效页面" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" -msgstr "游客的本地化是自动侦测而无法设置的" +msgstr "无法设置游客的本地化,该项设置的值将自动检测" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "无可用本地化" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "无有效书籍语言" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "参数未找到" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" -msgstr "无效的阅读列" +msgstr "无效的阅读栏目" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" -msgstr "无效的限制列" +msgstr "无效的限制栏目" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" -msgstr "Calibre-Web配置已更新" +msgstr "Calibre-Web 配置已更新" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" -msgstr "您确定删除Kobo Token吗?" +msgstr "您确定删除 Kobo 令牌吗?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "您确定要删除此域吗?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "您确定要删除此用户吗?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "您确定要删除此书架吗?" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "您确定要修改选定用户的本地化设置吗?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "您确定要修改选定用户的可见书籍语言吗?" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "您确定要修改选定用户的选定角色吗?" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "您确定要修改选定用户的选定限制吗?" -#: cps/admin.py:607 +#: 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:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "您确定要更改所选用户的书架同步行为吗?" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "您确定要更改 Calibre 库位置吗?" -#: cps/admin.py:614 +#: 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: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:764 -msgid "Tag not found" -msgstr "标签未找到" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "无效的动作" - -#: cps/admin.py:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} 同步项目被删除" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "标签未找到" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "无效的动作" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json 未为 Web 应用程序配置" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "日志文件路径无效,请输入正确的路径" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "访问日志路径无效,请输入正确的路径" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" -msgstr "请输入LDAP主机、端口、DN和用户对象标识符" +msgstr "请输入 LDAP 主机、端口、DN 和用户对象标识符" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" -msgstr "请输入一个LDAP服务账号和密码 " +msgstr "请输入一个 LDAP 服务账号和密码 " -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" -msgstr "请输入一个LDAP服务账号" +msgstr "请输入一个 LDAP 服务账号" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" -msgstr "LDAP组对象过滤器需要一个具有“%s”格式标识符" +msgstr "LDAP 组对象过滤器需要一个具有“%s”格式标识符" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" -msgstr "LDAP组对象过滤器的括号不匹配" +msgstr "LDAP 组对象过滤器的括号不匹配" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" -msgstr "LDAP用户对象过滤器需要一个具有“%s”格式标识符" +msgstr "LDAP 用户对象过滤器需要一个具有“%s”格式标识符" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" -msgstr "LDAP用户对象过滤器的括号不匹配" +msgstr "LDAP 用户对象过滤器的括号不匹配" -#: cps/admin.py:1169 +#: 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:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" -msgstr "LDAP成员用户过滤器中有不匹配的括号" +msgstr "LDAP 成员用户过滤器中有不匹配的括号" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CA证书、证书或密钥位置无效,请输入正确的路径" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "数据库错误:%(error)s。" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "数据库路径无效,请输入正确的路径" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "数据库不可写入" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "密钥文件路径无效,请输入正确的路径" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "证书文件路径无效,请输入正确的路径" - -#: cps/admin.py:1378 -msgid "Database Settings updated" -msgstr "数据库设置已更新" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "数据库配置" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "请填写所有字段!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "邮箱不在有效域中" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "添加新用户" -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "用户“%(user)s”已创建" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "使用此邮箱或用户名的账号已经存在。" - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "用户“%(nick)s”已删除" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "无法删除游客用户" - -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "管理员账户不存在,无法删除用户" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "编辑邮件服务器设置" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "编辑用户 %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gmail 账户验证成功" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "用户“%(nick)s”已更新" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "发生一个未知错误,请稍后再试。" +msgid "Oops! Database Error: %(error)s." +msgstr "数据库错误:%(error)s" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "编辑邮件服务器设置" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "G-Mail账号校验成功" - -#: cps/admin.py:1630 +#: 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:1633 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "发送测试邮件时出错:%(res)s" -#: cps/admin.py:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "请先配置您的邮箱地址..." -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "邮件服务器设置已更新" -#: cps/admin.py:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "编辑计划任务设置" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "指定任务的开始时间无效" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "指定任务的持续时间无效" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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:1394 +msgid "Settings DB is not Writeable" +msgstr "设置数据库不可写" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "编辑用户 %(nick)s" + +#: 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:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "日志文件查看器" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "正在请求更新包" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "正在下载更新包" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "正在解压更新包" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "正在替换文件" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "数据库连接已关闭" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "正在停止服务器" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "更新完成,请点击确定并刷新页面" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: 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:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "连接错误" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "建立连接超时" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "一般错误" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "更新文件无法保存在临时目录中" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "更新期间无法替换文件" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" -msgstr "未能提取至少一个LDAP用户" +msgstr "未能获得任何 LDAP 用户" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" -msgstr "未能创建至少一个LDAP用户" +msgstr "未能创建任何 LDAP 用户" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "错误:%(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" -msgstr "错误:在LDAP服务器的响应中没有返回用户" +msgstr "错误:在 LDAP 服务器的响应中没有返回用户" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" -msgstr "数据库中没有找到至少一个LDAP用户" +msgstr "数据库中没有找到任何 LDAP 用户" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 用户被成功导入" -#: cps/converter.py:30 -msgid "not installed" -msgstr "未安装" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "数据库路径无效,请输入正确的路径" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "缺少执行权限" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "数据库不可写入" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "自定义列号:%(column)d在Calibre数据库中不存在" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "密钥文件路径无效,请输入正确的路径" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "无" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "证书文件路径无效,请输入正确的路径" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "书籍格式已成功删除" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "密码长度必须在1到40之间" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "书籍已成功删除" +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "数据库设置已更新" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "您没有删除书籍的权限" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "数据库配置" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "糟糕!选择书名无法打开。文件不存在或者文件不可访问" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "请填写所有字段!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "编辑元数据" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "邮箱不在有效域中" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s 不是一个有效的数值,忽略" +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "添加新用户" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1920 #, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "'%(langname)s' 不是一种有效语言" +msgid "User '%(user)s' created" +msgstr "用户“%(user)s”已创建" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" -msgstr "用户没有权限上传其他文件格式" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "使用此邮箱或用户名的账号已经存在" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "不能上传文件扩展名为“%(ext)s”的文件到此服务器" +msgid "User '%(nick)s' deleted" +msgstr "用户“%(nick)s”已删除" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "要上传的文件必须具有扩展名" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "无法删除游客用户" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "创建路径 %(path)s 失败(权限拒绝)。" +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "管理员账户不存在,无法删除用户" -#: cps/editbooks.py:660 +#: 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:2043 #, python-format -msgid "Failed to store file %(file)s." -msgstr "保存文件 %(file)s 失败。" +msgid "User '%(nick)s' updated" +msgstr "用户“%(nick)s”已更新" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "未安装" -#: cps/editbooks.py:683 +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "缺少执行权限" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "已添加 %(ext)s 格式到 %(book)s" +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "自定义列号:%(column)d 在 Calibre 数据库中不存在" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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 "无" + +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "用户没有权限上传封面" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "标识符不区分大小写,覆盖旧标识符" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "已成功更新元数据" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "编辑书籍时出错: {}" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "文件 %(file)s 已上传" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "转换的源格式或目的格式缺失" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "书籍已经被成功加入 %(book_format)s 格式转换队列" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "转换此书籍时出现错误: %(res)s" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "上传的书籍可能已经存在,建议修改后重新上传: " -#: cps/editbooks.py:1041 +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s' 不是一种有效语言" + +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "要上传的文件必须具有扩展名" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "文件 %(filename)s 无法保存到临时目录" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "移动封面文件失败 %(file)s:%(error)s" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "书籍的此格式副本已成功删除" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "书籍已成功删除" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "您没有删除书籍的权限" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "编辑元数据" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "文件 %(file)s 已上传" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s 不是一个有效的数值,忽略" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "转换的源或目的格式缺失" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "用户没有权限上传其他文件格式" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "书籍已经被成功加入到 %(book_format)s 格式转换队列" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "创建路径 %(path)s 失败 (权限不足)" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "转换此书籍时出现错误: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "保存文件 %(file)s 失败" + +#: 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: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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" -msgstr "发送到Kindle" +#: 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:115 cps/helper.py:223 -msgid "This e-mail has been sent via Calibre-Web." -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:113 -msgid "Calibre-Web test e-mail" -msgstr "Calibre-Web测试邮件" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" +msgstr "Calibre-Web 测试邮件" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +msgid "Test Email" msgstr "测试邮件" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" -msgstr "开启Calibre-Web之旅" +msgstr "开启 Calibre-Web 之旅" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" -msgstr "转换 %(orig)s 到 %(format)s 并发送到Kindle" +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "转换 %(orig)s 到 %(format)s 并发送到电子阅读器" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to Kindle" -msgstr "发送 %(format)s 到Kindle" +msgid "Send %(format)s to eReader" +msgstr "发送 %(format)s 到电子阅读器" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to Kindle" -msgstr "%(book)s发送到Kindle" +msgid "%(book)s send to eReader" +msgstr "%(book)s 发送到电子阅读器" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "无法读取请求的文件。可能有错误的权限设置?" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "阅读状态无法设置: {}" -#: cps/helper.py:376 +#: 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:382 +#: 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:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "重命名此路径: {}文件时出错" -#: cps/helper.py:610 +#: 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:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "此用户名已被使用" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" -msgstr "无效的邮件地址格式" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "无效的邮箱格式" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" -msgstr "下载封面必须的 Python 模块'advocate' 未安装" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "密码不符合密码验证规则" -#: cps/helper.py:767 +#: 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:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "封面格式出错" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "您没有访问本地主机或本地网络进行封面上传" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "创建封面路径失败" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" -msgstr "封面文件不是有效的图片文件,或者无法存储" +msgstr "封面文件不是有效的图片文件,或者无法存储它" -#: cps/helper.py:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "封面文件内容无效" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" -msgstr "仅将jpg、jpeg文件作为封面文件" +msgstr "仅将 jpg、jpeg 文件作为封面文件" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" -msgstr "找不到Unrar执行文件" +msgstr "找不到 Unrar 执行文件" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" -msgstr "执行UnRar时出错" +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "执行 UnRar 时出错" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "等待中" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "失败" +#: cps/helper.py:1077 +msgid "Cover" +msgstr "封面" -#: cps/helper.py:941 -msgid "Started" -msgstr "已开始" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "将所有书籍加入元数据备份队列" -#: cps/helper.py:943 -msgid "Finished" -msgstr "已完成" - -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "未知状态" - -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 设置" @@ -795,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:1613 +#: 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: {}" @@ -850,521 +881,625 @@ 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:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} 星" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "书籍" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" -msgstr "显示最近书籍" +msgstr "显示最近查看的书籍" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "热门书籍" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "显示热门书籍" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" -msgstr "下载历史" +msgstr "已下载书籍" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "最高评分书籍" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" -msgstr "显示阅读状态" +#: cps/render_template.py:64 +msgid "Show Read and Unread" +msgstr "显示已读或未读状态" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "显示未读" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "发现" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "评分" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "文件格式" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "归档书籍" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "书籍列表" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "显示书籍列表" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "搜索" + +#: cps/search.py:188 +msgid "Published after " +msgstr "出版时间晚于 " + +#: cps/search.py:195 +msgid "Published before " +msgstr "出版时间早于 " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "评分 <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "评分 >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "阅读状态 = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "搜索自定义栏目时出错,请重启 Calibre-Web" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "高级搜索" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "指定的书架无效" -#: cps/shelf.py:73 +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" msgstr "对不起,您没有添加书籍到这个书架的权限" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "此书籍已经是书架 %(shelfname)s 的一部分" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "此书籍已被添加到书架:%(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "您没有向书架添加书籍的权限" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "书籍已经在书架 %(name)s 中了" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "书籍已经被添加到书架 %(sname)s 中" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "无法添加书籍到书架:%(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "此书已从书架 %(sname)s 中删除" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "抱歉,您没有从这个书架删除书籍的权限" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "创建书架" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" msgstr "对不起,您没有编辑这个书架的权限" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "编辑书架" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "删除书架时出错" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "书架已成功删除" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "修改书架 %(name)s 顺序" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "抱歉,您没有创建公开书架的权限" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "书架 %(title)s 已创建" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "书架 %(title)s 已修改" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "发生错误" -#: cps/shelf.py:304 +#: 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:315 +#: 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:337 -msgid "Error deleting Shelf" -msgstr "删除书架时出错" - -#: cps/shelf.py:339 -msgid "Shelf successfully deleted" -msgstr "书架已成功删除" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "修改书架 %(name)s 顺序" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "书架:%(name)s" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "打开书架出错。书架不存在或不可访问" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "任务列表" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "等待中" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "失败" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "已开始" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "已完成" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "已结束" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "已取消" + +#: 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:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "无可用更新。您已经安装了最新版本" -#: cps/updater.py:451 +#: 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:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "无法获取更新信息" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." -msgstr "点击下面按钮更新到最新稳定版本。" +msgstr "点击下面按钮更新到最新稳定版本" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "有新的更新。单击下面的按钮以更新到版本: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "无可用发布信息" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" -msgstr "发现(随机书籍)" +msgstr "发现 (随机书籍)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "热门书籍(最多下载)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s 下载过的书籍" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "作者:%(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社:%(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "丛书:%(serie)s" -#: cps/web.py:610 +#: 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:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "文件格式:%(format)s" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "分类:%(name)s" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "语言:%(name)s" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "高级搜索" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "搜索" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "下载次数" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "评分列表" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "文件格式列表" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "任务列表" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "出版时间晚于 " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "出版时间早于 " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "评分 <= %(rating)s" - -#: cps/web.py:1317 -#, python-format -msgid "Rating >= %(rating)s" -msgstr "评分 >= %(rating)s" - -#: cps/web.py:1319 -#, python-format -msgid "Read Status = %(status)s" -msgstr "阅读状态 = %(status)s" - -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "搜索自定义列时出错,请重启 Calibre-Web" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "请先配置 SMTP 邮箱设置..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "书籍已经成功加入 %(kindlemail)s 的发送队列" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "书籍已经成功加入 %(eReadermail)s 的发送队列" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" -msgstr "无法激活LDAP认证" +msgstr "无法激活 LDAP 认证" + +#: 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:1621 +#: 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:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "无法登录:%(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "用户名或密码错误" -#: cps/web.py:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "新密码已发送到您的邮箱" -#: cps/web.py:1644 +#: 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:1651 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "您现在已以“%(nickname)s”登录" +msgstr "您现在已以“%(nickname)s”身份登录" -#: cps/web.py:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "硬盘上找不到 %(format)s 格式" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "发生未知错误,书籍转换失败" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify 转换失败:%(error)s" -#: cps/tasks/convert.py:223 +#: 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:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "电子书转换器失败: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre 运行失败,错误信息:%(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "转换" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "正在重新连接到 Calibre 数据库" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "电子邮件" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "正在备份元数据" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "生成了 %(count)s 个封面缩略图" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "封面缩略图" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "生成了 %(count)s 个丛书缩略图" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "上传书籍" + #: cps/templates/admin.html:9 msgid "Users" msgstr "用户列表" @@ -1377,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 Kindle E-mail Address" -msgstr "接收书籍的Kindle邮箱地址" +msgid "Send to eReader Email" +msgstr "接收书籍的电子阅读器邮箱地址" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理权限" @@ -1394,13 +1529,8 @@ msgstr "管理权限" msgid "Password" msgstr "密码" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "上传书籍" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "下载书籍" @@ -1414,7 +1544,7 @@ msgstr "查看书籍" msgid "Edit" msgstr "编辑书籍" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1425,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" @@ -1451,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" @@ -1516,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" @@ -1526,78 +1652,109 @@ msgstr "编辑基本配置" msgid "Edit UI Configuration" msgstr "编辑界面配置" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "计划任务" + +#: 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 +msgid "Maximum Duration" +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 "生成丛书封面缩略图" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" -msgstr "下载Debug包" +msgstr "下载 Debug 包" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "查看日志文件" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "重新连接到Calibre数据库" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "重启" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "停止" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "更新" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "版本信息" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "版本" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "详情" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "当前版本" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "检查更新" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "执行更新" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "您确定要重启吗?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "您确定要关闭吗?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "正在更新,请不要刷新页面" @@ -1609,39 +1766,39 @@ msgstr "通过" msgid "In Library" msgstr "在书库" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "按图书日期排序,最新优先" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "按图书日期排序,最旧优先" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "按标题按字母顺序排序" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "按标题逆字母顺序排序" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "按出版日期排序,最新优先" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "按出版日期排序,最旧优先" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "减少" @@ -1649,166 +1806,167 @@ msgstr "减少" msgid "More by" msgstr "更多" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "删除书籍" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "删除格式:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" -msgstr "转换书籍格式:" +msgstr "书籍格式转换:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "转换从:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "选择一个选项" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "转换到:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "转换书籍" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "书名" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "作者" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "简介" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "书号" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "书号类型" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "书号编号" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "移除" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "添加书号" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "标签" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "丛书编号" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "评分" -#: cps/templates/book_edit.html:103 +#: 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:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "从本地磁盘上传封面" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "出版日期" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "出版社" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "没有" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "上传格式" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "查看保存书籍" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "获取元数据" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "保存" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "关键字" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 msgid "Search keyword" msgstr " 搜索关键字 " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "单击封面将元数据加载到表单" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "加载中..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "关闭" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "源" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "搜索错误!" -#: cps/templates/book_edit.html:287 +#: 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 @@ -1898,7 +2056,7 @@ msgid "Comments" msgstr "简介" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "存档状态" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1913,6 +2071,7 @@ 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 "您真的确认?" @@ -1934,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" @@ -1946,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" @@ -1966,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" @@ -1994,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" @@ -2002,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" @@ -2010,14 +2169,14 @@ msgstr "功能配置" #: cps/templates/config_edit.html:104 msgid "Convert non-English characters in title and author while saving to disk" -msgstr "保存到磁盘事转换标题和作者中的非英文字符" +msgstr "保存到磁盘时转换标题和作者中的非英文字符" #: cps/templates/config_edit.html:108 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 @@ -2033,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 @@ -2042,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" @@ -2082,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" @@ -2102,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" @@ -2138,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" @@ -2162,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" @@ -2186,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 @@ -2221,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" @@ -2235,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 "主题" @@ -2324,80 +2527,82 @@ msgstr "添加显示或隐藏书籍的标签值" msgid "Add Allowed/Denied custom column values" msgstr "添加显示或隐藏书籍的自定义栏目值" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "在线阅读" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "在线听书" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "出版日期" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "标为未读" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "标为已读" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "已读" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "从档案还原" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "添加到归档" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "归档" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "简介:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "添加到书架" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2405,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:29 +#: 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 "后退" @@ -2449,186 +2654,194 @@ msgstr "输入域名" msgid "Denied Domains (Blacklist)" msgstr "禁止注册的域名(黑名单)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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:" msgstr "Kobo Token:" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "列表" + +#: 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 "登出账号" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "按下载数排序" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "按下载数逆序排序" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "按作者字母顺序排序" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "按作者逆字母顺序排序" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "按丛书编号排序" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "首页" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "切换导航" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "搜索书库" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "正在上传..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "错误" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "上传完成,正在处理,请稍候..." -#: cps/templates/layout.html:76 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 "设置" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "账号" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "注销" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "请不要刷新页面" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "按条件浏览" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "关于" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "上一个" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "书籍详情" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "网格" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "记住我" @@ -2637,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: " @@ -2659,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" @@ -2667,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" @@ -2691,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" @@ -2703,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" @@ -2733,153 +2946,185 @@ msgstr "父目录" msgid "Select" msgstr "选择" -#: cps/templates/modal_dialogs.html:134 +#: 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 "Caliebre-Web电子书路径" +msgstr "Caliebre-Web 电子书路径" #: cps/templates/read.html:6 msgid "epub Reader" -msgstr "epub阅读器" +msgstr "epub 阅读器" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "浅色" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "深色" -#: cps/templates/read.html:75 +#: 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 "打开侧栏时重排文本。" +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:116 -msgid "Light" -msgstr "浅色" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "显示" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "深色" +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "单页" -#: cps/templates/readcbr.html:122 +#: 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" @@ -2890,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 @@ -2903,21 +3148,25 @@ 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分钟后失效。" +msgstr "此验证链接将在10分钟后失效" -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "生成丛书封面缩略图" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "无搜索结果" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "搜索项:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "结果:" @@ -2929,63 +3178,71 @@ 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 "到:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "删除此书架" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "编辑书架属性" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "手动排列书籍排列顺序" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "禁止改变顺序" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "允许改变顺序" @@ -3030,8 +3287,8 @@ msgid "System Statistics" msgstr "系统统计" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "程序名称" +msgid "Program" +msgstr "程序" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3057,9 +3314,17 @@ 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 "这个任务将被取消。此任务所有的更改都将被保存" + +#: 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" @@ -3071,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" @@ -3091,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" @@ -3107,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..." @@ -3122,16 +3387,16 @@ 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 Kindle E-mail Address" -msgstr "输入Kindle邮箱地址" +msgid "Enter eReader Email" +msgstr "接收书籍的电子阅读器邮箱" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "Kindle邮箱" +msgid "eReader Email" +msgstr "电子阅读器邮箱" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3139,7 +3404,7 @@ msgstr "本地化" #: cps/templates/user_table.html:138 msgid "Visible Book Languages" -msgstr "可见数据语言" +msgstr "可见书籍语言" #: cps/templates/user_table.html:139 msgid "Edit Allowed Tags" @@ -3151,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" @@ -3190,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 4dce851c..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 8f592870..7c340a9b 100644 --- a/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po +++ b/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po @@ -7,595 +7,639 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-04-18 20:01+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" "Language-Team: zh_Hans_CN \n" -"Plural-Forms: nplurals=1; plural=0\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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "統計" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "服務器已重啟,請刷新頁面" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "正在關閉服務器,請關閉窗口" -#: cps/admin.py:151 -msgid "Reconnect successful" -msgstr "重新連接成功" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "未知命令" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "發送給%(email)s的測試郵件已進入隊列。請檢查任務結果" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理頁" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本配置" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "界面配置" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "管理用戶" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "全部" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "找不到用戶" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "成功刪除 {} 個用戶" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "格式錯誤的請求" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "訪客名稱無法更改" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "遊客無法擁有此角色" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "管理員賬戶不存在,無法刪除管理員角色" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "值必須是 true 或 false" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "無效角色" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "遊客無法擁有此視圖" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "無效視圖" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "訪客的本地化是自動偵測而無法設置的" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "無可用本地化" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "無有效書籍語言" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "參數未找到" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "無效的閱讀列" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "無效的限制列" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web配置已更新" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "您確定刪除Kobo Token嗎?" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "您確定要刪除此網域嗎?" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "您確定要刪除此用戶嗎?" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "您確定要刪除此書架嗎?" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "您確定要修改選定用戶的本地化設置嗎?" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "您確定要修改選定用戶的可見書籍語言嗎?" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "您確定要修改選定用戶的選定角色嗎?" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "您確定要修改選定用戶的選定限制嗎?" -#: cps/admin.py:607 +#: 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:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "您確定要更改所選用戶的書架同步行為嗎?" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "您確定要更改 Calibre 庫位置嗎?" -#: cps/admin.py:614 -msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +#: 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:764 -msgid "Tag not found" -msgstr "標籤未找到" - -#: cps/admin.py:776 -msgid "Invalid Action" -msgstr "無效的動作" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "標籤未找到" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "無效的動作" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json 未為 Web 應用程序配置" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "日誌文件路徑無效,請輸入正確的路徑" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "訪問日誌路徑無效,請輸入正確的路徑" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "請輸入LDAP主機、端口、DN和用戶對象標識符" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "請輸入一個LDAP服務賬號和密碼 " -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "請輸入一個LDAP服務賬號" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP群組對象過濾器需要一個具有“%s”格式標識符號" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP群組對象過濾器的括號不匹配" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP用戶對象過濾器需要一個具有“%s”格式標識符" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP用戶對象過濾器的括號不匹配" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP成員用戶過濾器需要有一個“%s”格式標識符號" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP成員用戶過濾器中有不匹配的括號" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CA證書、證書或密鑰位置無效,請輸入正確的路徑" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "數據庫錯誤:%(error)s。" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "數據庫路徑無效,請輸入正確的路徑" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "數據庫不可寫入" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "密鑰文件路徑無效,請輸入正確的路徑" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "證書文件路徑無效,請輸入正確的路徑" - -#: cps/admin.py:1378 -#, fuzzy -msgid "Database Settings updated" -msgstr "郵件服務器設置已更新" - -#: cps/admin.py:1386 -msgid "Database Configuration" -msgstr "數據庫配置" - -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" -msgstr "請填寫所有欄位!" - -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" -msgstr "郵箱不在有效網域中" - -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "添加新用戶" -#: cps/admin.py:1427 -#, python-format -msgid "User '%(user)s' created" -msgstr "用戶“%(user)s”已創建" - -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." -msgstr "使用此郵箱或用戶名的賬號已經存在。" - -#: cps/admin.py:1463 -#, python-format -msgid "User '%(nick)s' deleted" -msgstr "用戶“%(nick)s”已刪除" - -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" -msgstr "無法刪除訪客用戶" - -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" -msgstr "管理員賬戶不存在,無法刪除用戶" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "編輯郵件服務器設置" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" -msgstr "編輯用戶 %(nick)s" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1546 +#: 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 "User '%(nick)s' updated" -msgstr "用戶“%(nick)s”已更新" - -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." -msgstr "發生一個未知錯誤,請稍後再試。" - -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" -msgstr "編輯郵件服務器設置" - -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" -msgstr "G-Mail賬號驗證成功" +msgid "Oops! Database Error: %(error)s." +msgstr "數據庫錯誤:%(error)s。" -#: cps/admin.py:1630 +#: 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:1633 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "發送測試郵件時出錯:%(res)s" -#: cps/admin.py:1635 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "請先配置您的郵箱地址..." -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "郵件服務器設置已更新" -#: cps/admin.py:1679 +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +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:1394 +msgid "Settings DB is not Writeable" +msgstr "" + +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "Password for user %(user)s reset" +msgid "Edit User %(nick)s" +msgstr "編輯用戶 %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "用戶 %(user)s 的密碼已重置" -#: cps/admin.py:1685 cps/web.py:1522 -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:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "日誌文件查看器" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "正在請求更新包" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "正在下載更新包" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "正在解壓更新包" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "正在替換文件" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "數據庫連接已關閉" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "正在停止服務器" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "更新完成,請點擊確定並刷新頁面" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP錯誤" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "連接錯誤" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "建立連接超時" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "一般錯誤" -#: cps/admin.py:1773 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "更新文件無法保存在臨時目錄中" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "更新時檔案無法替換變更" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "未能提取至少一個LDAP用戶" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "未能創建至少一個LDAP用戶" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "錯誤:%(ldaperror)s" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "錯誤:在LDAP服務器的響應中沒有返回用戶" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "數據庫中沒有找到至少一個LDAP用戶" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 用戶被成功導入" -#: cps/converter.py:30 -msgid "not installed" -msgstr "未安裝" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "數據庫路徑無效,請輸入正確的路徑" -#: cps/converter.py:31 -msgid "Execution permissions missing" -msgstr "缺少執行權限" +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "數據庫不可寫入" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" -msgstr "自定義列號:%(column)d在Calibre數據庫中不存在" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "密鑰文件路徑無效,請輸入正確的路徑" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" -msgstr "無" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "證書文件路徑無效,請輸入正確的路徑" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" -msgstr "書籍格式已成功刪除" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" -msgstr "書籍已成功刪除" +#: cps/admin.py:1871 +#, fuzzy +msgid "Database Settings updated" +msgstr "郵件服務器設置已更新" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" -msgstr "" +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "數據庫配置" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "糟糕!選擇書名無法打開。文件不存在或者文件不可訪問" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "請填寫所有欄位!" -#: cps/editbooks.py:408 -msgid "edit metadata" -msgstr "編輯元數據" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "郵箱不在有效網域中" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "添加新用戶" -#: cps/editbooks.py:457 +#: cps/admin.py:1920 #, python-format -msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s 不是一個有效的數值,忽略" +msgid "User '%(user)s' created" +msgstr "用戶“%(user)s”已創建" -#: cps/editbooks.py:493 cps/editbooks.py:1001 -#, fuzzy, python-format -msgid "'%(langname)s' is not a valid language" -msgstr "%(langname)s 不是一種有效語言" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "使用此郵箱或用戶名的賬號已經存在。" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "用戶“%(nick)s”已刪除" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "無法刪除訪客用戶" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "管理員賬戶不存在,無法刪除用戶" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:2043 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" -msgstr "不能上傳文件附檔名為“%(ext)s”的文件到此服務器" +msgid "User '%(nick)s' updated" +msgstr "用戶“%(nick)s”已更新" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" -msgstr "要上傳的文件必須具有附檔名" +#: cps/converter.py:31 +msgid "not installed" +msgstr "未安裝" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." -msgstr "創建路徑 %(path)s 失敗(權限拒絕)。" +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "缺少執行權限" -#: cps/editbooks.py:660 -#, python-format -msgid "Failed to store file %(file)s." -msgstr "保存文件 %(file)s 失敗。" +#: 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/editbooks.py:683 -#, python-format -msgid "File format %(ext)s added to %(book)s" -msgstr "已添加 %(ext)s 格式到 %(book)s" +#: 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 "無" + +#: 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:697 cps/editbooks.py:809 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "標識符不區分大小寫,覆蓋舊標識符" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "已成功更新元數據" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "文件 %(file)s 已上傳" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "轉換的來源或目的格式不存在" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "書籍已經被成功加入到 %(book_format)s 格式轉換隊列" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "轉換此書籍時出現錯誤: %(res)s" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "上傳的書籍可能已經存在,建議修改後重新上傳: " -#: cps/editbooks.py:1041 +#: 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: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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "要上傳的文件必須具有附檔名" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "文件 %(filename)s 無法保存到臨時目錄" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "移動封面文件失敗 %(file)s:%(error)s" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "書籍格式已成功刪除" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "書籍已成功刪除" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "編輯元數據" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" -msgstr "文件 %(file)s 已上傳" +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s 不是一個有效的數值,忽略" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" -msgstr "轉換的來源或目的格式不存在" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" -msgstr "書籍已經被成功加入到 %(book_format)s 格式轉換隊列" +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "創建路徑 %(path)s 失敗(權限拒絕)。" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" -msgstr "轉換此書籍時出現錯誤: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "保存文件 %(file)s 失敗。" + +#: 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" @@ -610,186 +654,184 @@ msgstr "回調網域名稱尚未被驗證,請在google開發者控制台按步 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" msgstr "發送到Kindle" -#: cps/helper.py:98 cps/helper.py:115 cps/helper.py:223 -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:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web測試郵件" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "測試郵件" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "開啟Calibre-Web之旅" -#: cps/helper.py:136 -#, 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:147 cps/helper.py:153 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +#: 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 並發送到Kindle" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 -#, python-format -msgid "Send %(format)s to Kindle" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "發送 %(format)s 到Kindle" -#: cps/helper.py:220 cps/tasks/convert.py:92 -#, python-format -msgid "%(book)s send to Kindle" +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" msgstr "%(book)s發送到Kindle" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "無法讀取請求的文件。可能有錯誤的權限設置?" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: 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:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "刪除書籍 %(id)s失敗:%(message)s" -#: cps/helper.py:393 +#: 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:458 +#: 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:529 cps/helper.py:538 +#: 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:572 +#: 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:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Google Drive上找不到書籍路徑 %(path)s" -#: cps/helper.py:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "此用戶名已被使用" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "無效的郵件地址格式" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: 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:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "下載封面時出錯" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "封面格式出錯" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "創建封面路徑失敗" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "封面文件不是有效的圖片文件,或者無法儲存" -#: cps/helper.py:810 +#: 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:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "僅將jpg、jpeg文件作為封面文件" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "找不到Unrar執行文件" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" msgstr "執行UnRar時出錯" -#: cps/helper.py:937 -msgid "Waiting" -msgstr "等待中" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "失敗" - -#: cps/helper.py:941 -msgid "Started" -msgstr "已開始" - -#: cps/helper.py:943 -msgid "Finished" -msgstr "已完成" +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "發現" -#: cps/helper.py:945 -msgid "Unknown Status" -msgstr "未知狀態" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 設置" @@ -798,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:1613 +#: 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 @@ -859,12 +901,13 @@ msgstr "Google Oauth 錯誤,請重試。" msgid "Google Oauth error: {}" msgstr "Google Oauth 錯誤: {}" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} 星" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "登入" @@ -880,495 +923,616 @@ msgstr "Token已過期" msgid "Success! Please return to your device" msgstr "成功!請返回您的設備" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "書籍" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "顯示最近書籍" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "熱門書籍" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "顯示熱門書籍" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "已下載書籍" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "最高評分書籍" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "顯示閱讀狀態" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "顯示未讀" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "發現" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "評分" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "文件格式" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "歸檔書籍" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "書籍列表" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "顯示書籍列表" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "搜尋" + +#: cps/search.py:188 +msgid "Published after " +msgstr "出版時間晚於 " + +#: cps/search.py:195 +msgid "Published before " +msgstr "出版時間早於 " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "評分 <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "評分 >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "閱讀狀態 = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "搜詢自定義欄位時出錯,請重啟 Calibre-Web" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "進階搜尋" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "指定的書架無效" -#: cps/shelf.py:73 +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" msgstr "對不起,您沒有添加書籍到這個書架的權限" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "此書籍已經是書架 %(shelfname)s 的一部分" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "此書籍已被添加到書架:%(sname)s" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "書籍已經在書架 %(name)s 中了" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "書籍已經被添加到書架 %(sname)s 中" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "無法添加書籍到書架:%(sname)s" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "此書已從書架 %(sname)s 中刪除" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "創建書架" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" msgstr "對不起,您沒有編輯這個書架的權限" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "編輯書架" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +#, fuzzy +msgid "Shelf successfully deleted" +msgstr "書籍已成功刪除" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "修改書架 %(name)s 順序" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "書架 %(title)s 已創建" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "書架 %(title)s 已修改" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "發生錯誤" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "公共書架:%(title)s已經存在已經存在。" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "私有書架:%(title)s已經存在。" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" -msgstr "" - -#: cps/shelf.py:339 -#, fuzzy -msgid "Shelf successfully deleted" -msgstr "書籍已成功刪除" - -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" -msgstr "修改書架 %(name)s 順序" - -#: cps/shelf.py:461 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "書架:%(name)s" -#: cps/shelf.py:465 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "打開書架出錯。書架不存在或不可訪問" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "任務列表" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "等待中" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "失敗" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "已開始" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "已完成" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: 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 "讀取更新信息時出現未預期數據" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "無可用更新。您已經安裝了最新版本" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "有新的更新。單擊下面的按鈕以更新到最新版本。" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "無法獲取更新信息" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "點擊下面按鈕更新到最新穩定版本。" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "有新的更新。單擊下面的按鈕以更新到版本: %(version)s" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "無可用發佈信息" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "發現(隨機書籍)" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "熱門書籍(最多下載)" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s 下載過的書籍" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "作者:%(name)s" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社:%(name)s" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "叢書:%(serie)s" -#: cps/web.py:610 +#: 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:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" -msgstr "文件格式:%(format)s" - -#: cps/web.py:663 -#, python-format -msgid "Category: %(name)s" -msgstr "分類:%(name)s" - -#: cps/web.py:690 -#, python-format -msgid "Language: %(name)s" -msgstr "語言:%(name)s" - -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "進階搜尋" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "搜尋" - -#: cps/templates/admin.html:16 cps/web.py:979 -msgid "Downloads" -msgstr "下載次數" - -#: cps/web.py:1068 -msgid "Ratings list" -msgstr "評分列表" - -#: cps/web.py:1095 -msgid "File formats list" -msgstr "文件格式列表" - -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "任務列表" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "出版時間晚於 " - -#: cps/web.py:1293 -msgid "Published before " -msgstr "出版時間早於 " - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" -msgstr "評分 <= %(rating)s" +msgstr "文件格式:%(format)s" -#: cps/web.py:1317 +#: cps/web.py:682 #, python-format -msgid "Rating >= %(rating)s" -msgstr "評分 >= %(rating)s" +msgid "Category: %(name)s" +msgstr "分類:%(name)s" -#: cps/web.py:1319 +#: cps/web.py:711 #, python-format -msgid "Read Status = %(status)s" -msgstr "閱讀狀態 = %(status)s" +msgid "Language: %(name)s" +msgstr "語言:%(name)s" -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "搜詢自定義欄位時出錯,請重啟 Calibre-Web" +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "下載次數" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "評分列表" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "文件格式列表" + +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "請先配置SMTP郵箱設置..." -#: cps/web.py:1527 +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "書籍已經成功加入 %(kindlemail)s 的發送隊列" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "書籍已經成功加入 %(eReadermail)s 的發送隊列" -#: cps/web.py:1531 +#: 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:1533 -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:1550 -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:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 +#: 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:1585 -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:1588 -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:1602 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "無法激活LDAP認證" -#: cps/web.py:1621 -#, 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:1627 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "無法登入:%(message)s" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "用戶名或密碼錯誤" -#: cps/web.py:1638 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "新密碼已發送到您的郵箱" -#: cps/web.py:1644 +#: 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:1651 -#, 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:1717 cps/web.py:1766 +#: 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:1733 -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:154 +#: 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" msgstr "沒有發現Calibre 電子書轉換器%(tool)s" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "硬碟上找不到 %(format)s 格式" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "發生未知錯誤,書籍轉換失敗" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "Kepubify 轉換失敗:%(error)s" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "找不到轉換後的文件或文件夾%(folder)s中有多個文件" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "電子書轉換器失敗: %(error)s" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "Calibre 運行失敗,錯誤信息:%(error)s" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "編輯元數據" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "上傳書籍" + #: cps/templates/admin.html:9 msgid "Users" msgstr "用戶列表" @@ -1381,14 +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 -msgid "Send to Kindle E-mail Address" +#, fuzzy +msgid "Send to eReader Email" msgstr "接收書籍的Kindle郵箱地址" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理權限" @@ -1398,13 +1563,8 @@ msgstr "管理權限" msgid "Password" msgstr "密碼" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "上傳書籍" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "下載書籍" @@ -1418,7 +1578,7 @@ msgstr "查看書籍" msgid "Edit" msgstr "編輯書籍" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1429,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 @@ -1459,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 @@ -1530,78 +1687,109 @@ msgstr "編輯基本配置" msgid "Edit UI Configuration" msgstr "編輯界面配置" -#: cps/templates/admin.html:166 +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "" + +#: 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 +msgid "Maximum Duration" +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 "" + +#: 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: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:167 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "下載除錯包" -#: cps/templates/admin.html:168 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "查看日誌文件" -#: cps/templates/admin.html:171 -msgid "Reconnect Calibre Database" -msgstr "重新連接到Calibre數據庫" - -#: cps/templates/admin.html:172 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "重啟" -#: cps/templates/admin.html:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "停止" -#: cps/templates/admin.html:178 -msgid "Update" -msgstr "更新" +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "版本" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "詳情" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "當前版本" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "檢查更新" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "執行更新" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "您確定要重啟嗎?" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "您確定要關閉嗎?" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "正在更新,請不要刷新頁面" @@ -1613,39 +1801,39 @@ msgstr "通過" msgid "In Library" msgstr "在書庫" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "按圖書日期排序,最新優先" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "按圖書日期排序,最舊優先" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "按標題按字母順序排序" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "按標題逆字母順序排序" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "按出版日期排序,最新優先" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "按出版日期排序,最舊優先" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "減少" @@ -1653,165 +1841,166 @@ msgstr "減少" msgid "More by" msgstr "更多" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "刪除書籍" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "刪除格式:" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "轉換書籍格式:" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "轉換從:" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "選擇一個選項" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "轉換到:" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "轉換書籍" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "書名" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "作者" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "簡介" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "書號" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "書號類型" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "書號編號" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "移除" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "添加書號" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "標籤" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "叢書編號" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "評分" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "從URL獲取封面(JPEG - 圖片將下載並存儲在數據庫中)" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "從本地硬碟上傳封面" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "出版日期" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "出版社" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "沒有" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "上傳格式" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "查看保存書籍" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "獲取元數據" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "儲存" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "關鍵字" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 #, fuzzy msgid "Search keyword" msgstr " 搜索關鍵字 " -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "單擊封面將元數據加載到表單" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "加載中..." -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "關閉" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "來源" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "搜索錯誤!" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "無搜索結果!請嘗試另一個關鍵字。" @@ -1904,7 +2093,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1920,6 +2109,7 @@ 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 "您真的確認?" @@ -2024,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 @@ -2040,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 @@ -2230,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 "查看配置" @@ -2242,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 "主題" @@ -2333,80 +2569,84 @@ msgstr "添加顯示或隱藏書籍的標籤值" msgid "Add Allowed/Denied custom column values" msgstr "添加顯示或隱藏書籍的自定義欄位值" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "在線閱讀" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "在線聽書" -#: cps/templates/detail.html:124 +#: 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:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "出版日期" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "標為未讀" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "標為已讀" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "已讀" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "從歸檔檔案還原" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "添加到歸檔" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "歸檔" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "簡介:" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "添加到書架" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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" @@ -2429,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:29 +#: 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 "後退" @@ -2458,187 +2699,195 @@ msgstr "輸入網域名" msgid "Denied Domains (Blacklist)" msgstr "禁止註冊的網域名(黑名單)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "Kobo 同步 Token" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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 "登出賬號" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "按作者字母順序排序" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "按作者逆字母順序排序" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "按叢書編號排序" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "首頁" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "切換導航" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "搜索書庫" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 +#: 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 msgid "Uploading..." msgstr "正在上傳..." -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Error" msgstr "錯誤" -#: cps/templates/layout.html:63 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "上傳完成,正在處理中,請稍候..." -#: cps/templates/layout.html:76 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 "設置" -#: cps/templates/layout.html:78 -msgid "Account" -msgstr "賬號" - -#: cps/templates/layout.html:80 -msgid "Logout" -msgstr "登出" - -#: cps/templates/layout.html:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "請不要刷新頁面" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "瀏覽" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "關於" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "上一個" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "書籍詳情" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "記住我" @@ -2647,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 "通過魔法連接登入" @@ -2743,7 +2992,7 @@ msgstr "父目錄" msgid "Select" msgstr "選擇" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "完成" @@ -2755,127 +3004,161 @@ msgstr "Caliebre-Web電子書路徑" msgid "epub Reader" msgstr "epub閱讀器" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "淺色" + +#: 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 +#, fuzzy +msgid "Black" +msgstr "後退" + +#: 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:116 -msgid "Light" -msgstr "淺色" +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" -msgstr "深色" +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "管理頁" -#: cps/templates/readcbr.html:122 +#: 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 "隱藏" @@ -2883,7 +3166,7 @@ msgstr "隱藏" msgid "DJVU Reader" msgstr "DJVU閱讀器" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDF閱讀器" @@ -2900,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 @@ -2919,15 +3202,19 @@ msgstr "驗證後,您將自動在新設備上登入。" msgid "This verification link will expire in 10 minutes." msgstr "此驗證連接將在10分鐘後失效。" -#: cps/templates/search.html:5 +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "" + +#: cps/templates/search.html:6 msgid "No Results Found" msgstr "無搜索結果" -#: cps/templates/search.html:6 +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "搜索項:" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "結果:" @@ -2939,63 +3226,71 @@ 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 "到:" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "刪除此書架" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "編輯書架屬性" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "手動排列書籍排列順序" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "禁止改變順序" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "允許改變順序" @@ -3040,8 +3335,8 @@ msgid "System Statistics" msgstr "系統統計" #: cps/templates/stats.html:33 -msgid "Program Library" -msgstr "程式名稱" +msgid "Program" +msgstr "" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3067,9 +3362,17 @@ 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 "" + +#: 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" @@ -3132,16 +3435,19 @@ 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 Kindle E-mail Address" -msgstr "輸入Kindle郵箱地址" +#, fuzzy +msgid "Enter eReader Email" +msgstr "接收書籍的Kindle郵箱地址" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" -msgstr "Kindle郵箱" +#, fuzzy +msgid "eReader Email" +msgstr "測試郵件" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3200,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 fd7a90ef..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) @@ -263,7 +264,7 @@ class OAuthProvider(Base): active = Column(Boolean) -# Class for anonymous user is derived from User base and completly overrides methods and properties for the +# Class for anonymous user is derived from User base and completely overrides methods and properties for the # anonymous user class Anonymous(AnonymousUserMixin, UserBase): def __init__(self): @@ -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) @@ -769,7 +783,7 @@ def update_download(book_id, user_id): session.rollback() -# Delete non exisiting downloaded books in calibre-web's own database +# Delete non existing downloaded books in calibre-web's own database def delete_download(book_id): session.query(Downloads).filter(book_id == Downloads.book_id).delete() try: @@ -796,6 +810,7 @@ def create_anonymous_user(_session): def create_admin_user(_session): user = User() user.name = "admin" + user.email = "admin@example.org" user.role = constants.ADMIN_USER_ROLES user.sidebar_view = constants.ADMIN_USER_SIDEBAR @@ -809,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) @@ -837,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() @@ -844,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) @@ -857,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..67b3653f 100644 --- a/cps/updater.py +++ b/cps/updater.py @@ -25,13 +25,13 @@ import threading import time import zipfile from io import BytesIO -from tempfile import gettempdir - import requests + from flask_babel import format_datetime from flask_babel import gettext as _ from . import constants, logger # config, web_server +from .file_helper import get_temp_dir log = logger.create() @@ -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') - tmp_dir = gettempdir() + log.debug('Extracting zipfile') + tmp_dir = get_temp_dir() 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'] @@ -566,7 +566,7 @@ class Updater(threading.Thread): try: current_version[2] = int(current_version[2]) except ValueError: - current_version[2] = int(current_version[2].split(' ')[0])-1 + current_version[2] = int(current_version[2].replace("b", "").split(' ')[0])-1 # Check if major versions are identical search for newest non-equal commit and update to this one if major_version_update == current_version[0]: diff --git a/cps/uploader.py b/cps/uploader.py index 5dbd1249..8f20762f 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -18,12 +18,12 @@ import os import hashlib -from tempfile import gettempdir from flask_babel import gettext as _ from . import logger, comic, isoLanguages from .constants import BookMeta from .helper import split_authors +from .file_helper import get_temp_dir log = logger.create() @@ -37,17 +37,22 @@ except (ImportError, RuntimeError) as e: use_generic_pdf_cover = True try: - from PyPDF3 import PdfFileReader - from PyPDF3 import __version__ as PyPdfVersion + from pypdf import PdfReader use_pdf_meta = True except ImportError as ex: + log.debug('PyPDF is recommended for best performance in metadata extracting from pdf files: %s', ex) try: - from PyPDF2 import PdfFileReader - from PyPDF2 import __version__ as PyPdfVersion + 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', ex, 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 @@ -64,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: @@ -74,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): @@ -94,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="", @@ -112,9 +117,9 @@ 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 XMP metadata {}'.format(ex)) + log.debug('Can not read PDF XMP metadata {}'.format(ex)) return None if xmp_info: @@ -158,8 +163,11 @@ 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.metadata + except Exception as exc: + log.debug('Can not read PDF DocumentInfo {}'.format(exc)) xmp_info = parse_xmp(pdf_file) if xmp_info: @@ -170,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 = "" @@ -179,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 == '': @@ -231,20 +239,17 @@ def pdf_preview(tmp_file_path, tmp_dir): return None -def get_versions(): +def get_magick_version(): ret = dict() 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): - tmp_dir = os.path.join(gettempdir(), 'calibre_web') - - if not os.path.isdir(tmp_dir): - os.mkdir(tmp_dir) +def upload(uploadfile, rar_excecutable): + tmp_dir = get_temp_dir() filename = uploadfile.filename filename_root, file_extension = os.path.splitext(filename) @@ -252,4 +257,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 1aa4cc1b..24c5cacd 100644 --- a/cps/web.py +++ b/cps/web.py @@ -25,13 +25,15 @@ 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_ +from sqlalchemy.sql.expression import text, func, false, not_, and_, or_ from sqlalchemy.orm.attributes import flag_modified from sqlalchemy.sql.functions import coalesce @@ -45,8 +47,8 @@ from .search import render_search_results, render_adv_search_results 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_kindle, check_read_formats, tags_filters, reset_password, valid_email, \ - edit_book_read_status + send_registration_mail, check_send_to_ereader, check_read_formats, tags_filters, reset_password, valid_email, \ + edit_book_read_status, valid_password from .pagination import Pagination from .redirect import redirect_back from .babel import get_available_locale @@ -54,6 +56,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), @@ -82,15 +88,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' @@ -387,7 +396,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": @@ -402,7 +411,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): @@ -417,7 +426,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) @@ -429,7 +438,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) @@ -437,7 +446,7 @@ def render_discover_books(book_id): def render_hot_books(page, order): if current_user.check_visibility(constants.SIDEBAR_HOT): if order[1] not in ['hotasc', 'hotdesc']: - # Unary expression comparsion only working (for this expression) in sqlalchemy 1.4+ + # Unary expression comparison only working (for this expression) in sqlalchemy 1.4+ # if not (order[0][0].compare(func.count(ub.Downloads.book_id).desc()) or # order[0][0].compare(func.count(ub.Downloads.book_id).asc())): order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc' @@ -465,7 +474,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) @@ -475,7 +484,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, @@ -490,13 +500,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: @@ -513,7 +522,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: @@ -529,7 +538,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]) @@ -565,7 +574,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]) @@ -593,35 +602,35 @@ 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): if book_id == '-1': + db_filter = coalesce(db.Ratings.rating, 0) < 1 entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, - db.Books.ratings == None, + db_filter, [order[0][0]], True, config.config_read_column, db.books_series_link, db.Books.id == db.books_series_link.c.book, - db.Series) - title = _(u"Rating: None") - rating = -1 + db.Series, + db.books_ratings_link, db.Ratings) + 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): @@ -633,7 +642,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: @@ -670,13 +679,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: @@ -697,7 +708,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): @@ -715,9 +726,9 @@ def render_read_books(page, are_read, as_xml=False, order=None): else: db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) if not as_xml: - flash(_("Custom Column No.%(column)d is not existing in calibre database", + flash(_("Custom Column No.%(column)d does not exist in calibre database", column=config.config_read_column), category="error") return redirect(url_for("web.index")) @@ -736,10 +747,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]) @@ -762,7 +773,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]) @@ -793,7 +804,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) @@ -914,7 +925,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) @@ -935,7 +946,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) @@ -963,7 +974,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) @@ -991,15 +1002,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) @@ -1018,16 +1037,18 @@ def ratings_list(): entries = calibre_db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'), (db.Ratings.rating / 2).label('name')) \ .join(db.books_ratings_link).join(db.Books).filter(calibre_db.common_filters()) \ + .filter(db.Ratings.rating > 0) \ .group_by(text('books_ratings_link.rating')).order_by(order).all() no_rating_count = (calibre_db.session.query(db.Books) .outerjoin(db.books_ratings_link).outerjoin(db.Ratings) - .filter(db.Ratings.rating == None) + .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) @@ -1054,7 +1075,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) @@ -1062,12 +1083,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) @@ -1084,7 +1105,7 @@ def category_list(): order_no = 1 entries = calibre_db.session.query(db.Tags, func.count('books_tags_link.book').label('count')) \ .join(db.books_tags_link).join(db.Books).order_by(order).filter(calibre_db.common_filters()) \ - .group_by(text('books_tags_link.tag')).all() + .group_by(db.Tags.id).all() no_tag_count = (calibre_db.session.query(db.Books) .outerjoin(db.books_tags_link).outerjoin(db.Tags) .filter(db.Tags.name == None) @@ -1095,7 +1116,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) @@ -1153,11 +1174,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: @@ -1165,16 +1190,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), + rawdata = open(os.path.join(config.get_book_path(), 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.get_book_path(), 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'}) @@ -1187,156 +1226,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_kindle(book_id, book_format, convert): +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, + result = send_mail(book_id, book_format, convert, current_user.kindle_mail, config.get_book_path(), 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=['GET', 'POST']) -def register(): +@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(_(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") + 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") - 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") + 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: - nickname = check_username(nickname) - email = check_email(to_save.get("email", "")) - except Exception as ex: - flash(str(ex), category="error") + 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')) - 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')) +@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(_("Oops! Email server is not configured, please contact your administrator."), category="error") + return render_title_template('register.html', title=_("Register"), page="register") 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 and form['password'] != "": - login_result, error = services.ldap.bind_user(form['username'], form['password']) - if login_result: - 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")) - 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") + return render_login() + + +@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() + username = form.get('username', "").strip().lower().replace("\n","").replace("\r","") + try: + limiter.check() + except RateLimitExceeded: + flash(_(u"Please wait one minute before next login"), category="error") + return render_login(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) == username).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(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', 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', 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(username, ip_address)) + flash(_(u"Wrong Username or Password"), category="error") + return render_login(username, form.get("password", "")) @web.route('/logout') @@ -1347,7 +1426,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')) @@ -1355,14 +1434,17 @@ 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")) - if to_save.get("email", current_user.email) != current_user.email: - current_user.email = check_email(to_save.get("email")) + new_email = valid_email(to_save.get("email", current_user.email)) + if not new_email: + 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(): if to_save.get("name", current_user.name) != current_user.name: # Query username, if not existing, change @@ -1382,10 +1464,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, @@ -1401,16 +1484,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"]) @@ -1433,8 +1516,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) @@ -1448,14 +1532,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: @@ -1463,22 +1548,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"]: @@ -1489,11 +1574,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")) @@ -1521,7 +1606,7 @@ def show_book(book_id): entry.ordered_authors = calibre_db.order_authors([entry]) - entry.kindle_list = check_send_to_kindle(entry) + entry.email_share_list = check_send_to_ereader(entry) entry.reader_list = check_read_formats(entry) entry.audio_entries = [] @@ -1537,7 +1622,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 4477a138..c683f205 100644 --- a/messages.pot +++ b/messages.pot @@ -1,597 +1,637 @@ # 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-04-18 20:01+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.9.1\n" +"Generated-By: Babel 2.13.1\n" -#: cps/about.py:86 +#: cps/about.py:84 msgid "Statistics" msgstr "" -#: cps/admin.py:141 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." msgstr "" -#: cps/admin.py:143 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." msgstr "" -#: cps/admin.py:151 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:154 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:176 cps/editbooks.py:713 cps/editbooks.py:892 -#: cps/editbooks.py:894 cps/editbooks.py:930 cps/editbooks.py:947 -#: cps/updater.py:608 cps/uploader.py:93 cps/uploader.py:103 +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "" + +#: 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:197 +#: cps/admin.py:231 msgid "Admin page" msgstr "" -#: cps/admin.py:217 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "" -#: cps/admin.py:255 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "" -#: cps/admin.py:289 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "" -#: cps/admin.py:333 cps/opds.py:529 cps/templates/grid.html:13 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:360 cps/admin.py:1648 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:374 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:397 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:418 cps/admin.py:424 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:436 cps/admin.py:1526 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:448 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:460 cps/admin.py:1484 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:464 cps/admin.py:478 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:466 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:470 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:480 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:483 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:487 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:498 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:500 cps/editbooks.py:1267 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:553 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:559 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:579 cps/admin.py:1355 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:591 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:593 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:595 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:597 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "" -#: cps/admin.py:599 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "" -#: cps/admin.py:601 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:603 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:605 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:607 +#: 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:610 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "" -#: cps/admin.py:612 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "" -#: cps/admin.py:614 -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:764 -msgid "Tag not found" +#: 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:776 -msgid "Invalid Action" +#: 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:893 cps/admin.py:899 cps/admin.py:909 cps/admin.py:919 +#: 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:895 cps/admin.py:901 cps/admin.py:911 cps/admin.py:921 +#: 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:936 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:1059 +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "" + +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1104 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1110 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1140 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1146 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1149 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1154 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1156 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1160 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1162 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1169 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1171 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1178 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1223 cps/admin.py:1339 cps/admin.py:1437 cps/admin.py:1554 -#: cps/admin.py:1623 cps/editbooks.py:678 cps/editbooks.py:882 -#: cps/editbooks.py:1130 cps/shelf.py:100 cps/shelf.py:160 cps/shelf.py:203 -#: cps/shelf.py:278 cps/shelf.py:343 cps/shelf.py:380 cps/shelf.py:456 -#: cps/web.py:1742 -#, python-format -msgid "Database error: %(error)s." -msgstr "" - -#: cps/admin.py:1235 -msgid "DB Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1253 -msgid "DB is not Writeable" -msgstr "" - -#: cps/admin.py:1266 -msgid "Keyfile Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1270 -msgid "Certfile Location is not Valid, Please Enter Correct Path" -msgstr "" - -#: cps/admin.py:1378 -msgid "Database Settings updated" -msgstr "" - -#: cps/admin.py:1386 -msgid "Database Configuration" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1402 cps/web.py:1557 -msgid "Please fill out all fields!" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "" -#: cps/admin.py:1410 -msgid "E-mail is not from valid domain" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1416 cps/admin.py:1576 -msgid "Add new user" -msgstr "" - -#: cps/admin.py:1427 +#: 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 "User '%(user)s' created" +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1433 -msgid "Found an existing account for this e-mail address or name." +#: 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:1463 +#: cps/admin.py:1326 #, python-format -msgid "User '%(nick)s' deleted" +msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1465 cps/admin.py:1466 -msgid "Can't delete Guest User" +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1469 -msgid "No admin user remaining, can't delete user" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1542 cps/admin.py:1667 -#, python-format -msgid "Edit User %(nick)s" +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1546 -#, python-format -msgid "User '%(nick)s' updated" +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1550 cps/admin.py:1682 cps/web.py:1582 cps/web.py:1642 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1585 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1604 -msgid "Gmail Account Verification Successful" +#: 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:1630 -#, python-format -msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1633 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format -msgid "There was an error sending the Test e-mail: %(res)s" -msgstr "" - -#: cps/admin.py:1635 -msgid "Please configure your e-mail address first..." -msgstr "" - -#: cps/admin.py:1637 -msgid "E-mail server settings updated" +msgid "Edit User %(nick)s" msgstr "" -#: cps/admin.py:1679 +#: 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:1685 cps/web.py:1522 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." msgstr "" -#: cps/admin.py:1696 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1762 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "" -#: cps/admin.py:1763 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "" -#: cps/admin.py:1764 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "" -#: cps/admin.py:1765 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "" -#: cps/admin.py:1766 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "" -#: cps/admin.py:1767 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "" -#: cps/admin.py:1768 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "" -#: cps/admin.py:1769 cps/admin.py:1770 cps/admin.py:1771 cps/admin.py:1772 -#: cps/admin.py:1773 cps/admin.py:1774 +#: 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:1769 cps/updater.py:384 cps/updater.py:619 cps/updater.py:621 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "" -#: cps/admin.py:1770 cps/updater.py:386 cps/updater.py:623 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "" -#: cps/admin.py:1771 cps/updater.py:388 cps/updater.py:625 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1772 cps/updater.py:390 cps/updater.py:627 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "" -#: cps/admin.py:1773 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1774 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1798 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1843 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1856 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1860 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1893 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1895 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/converter.py:30 -msgid "not installed" +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/converter.py:31 -msgid "Execution permissions missing" +#: cps/admin.py:1730 +msgid "DB is not Writeable" msgstr "" -#: cps/db.py:674 cps/web.py:710 cps/web.py:1222 -#, python-format -msgid "Custom Column No.%(column)d is not existing in calibre database" +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/db.py:917 cps/templates/config_edit.html:204 -#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:551 cps/web.py:585 cps/web.py:646 cps/web.py:671 cps/web.py:1003 -#: cps/web.py:1032 cps/web.py:1066 cps/web.py:1093 cps/web.py:1132 -msgid "None" +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/editbooks.py:295 cps/editbooks.py:297 -msgid "Book Format Successfully Deleted" +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" msgstr "" -#: cps/editbooks.py:304 cps/editbooks.py:306 -msgid "Book Successfully Deleted" +#: cps/admin.py:1871 +msgid "Database Settings updated" msgstr "" -#: cps/editbooks.py:358 -msgid "You are missing permissions to delete books" +#: cps/admin.py:1879 +msgid "Database Configuration" msgstr "" -#: cps/editbooks.py:373 cps/editbooks.py:765 cps/web.py:518 cps/web.py:1783 -#: cps/web.py:1825 cps/web.py:1870 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "" -#: cps/editbooks.py:408 -msgid "edit metadata" +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" msgstr "" -#: cps/editbooks.py:457 -#, python-format -msgid "%(seriesindex)s is not a valid number, skipping" +#: cps/admin.py:1909 +msgid "Add new user" msgstr "" -#: cps/editbooks.py:493 cps/editbooks.py:1001 +#: cps/admin.py:1920 #, python-format -msgid "'%(langname)s' is not a valid language" +msgid "User '%(user)s' created" msgstr "" -#: cps/editbooks.py:634 -msgid "User has no rights to upload additional file formats" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/editbooks.py:639 cps/editbooks.py:1029 +#: cps/admin.py:1956 #, python-format -msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgid "User '%(nick)s' deleted" msgstr "" -#: cps/editbooks.py:643 cps/editbooks.py:1033 -msgid "File to be uploaded must have an extension" +#: cps/admin.py:1959 +msgid "Can't delete Guest User" msgstr "" -#: cps/editbooks.py:655 -#, python-format -msgid "Failed to create path %(path)s (Permission denied)." +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/editbooks.py:660 +#: cps/admin.py:2043 #, python-format -msgid "Failed to store file %(file)s." +msgid "User '%(nick)s' updated" msgstr "" -#: cps/editbooks.py:683 +#: cps/converter.py:31 +msgid "not installed" +msgstr "" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format -msgid "File format %(ext)s added to %(book)s" +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "" + +#: 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 "" -#: cps/editbooks.py:697 cps/editbooks.py:809 +#: 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:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:828 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:869 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:887 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:951 +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "" + +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:1041 +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "" + +#: 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:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "" + +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:1061 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:1117 +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "" + +#: cps/editbooks.py:992 #, python-format -msgid "File %(file)s uploaded" +msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1143 -msgid "Source or destination format for conversion missing" +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1151 +#: cps/editbooks.py:1195 #, python-format -msgid "Book successfully queued for converting to %(book_format)s" +msgid "Failed to create path %(path)s (Permission denied)." msgstr "" -#: cps/editbooks.py:1155 +#: cps/editbooks.py:1200 #, python-format -msgid "There was an error converting this book: %(res)s" +msgid "Failed to store file %(file)s." +msgstr "" + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" msgstr "" #: cps/gdrive.py:58 @@ -607,185 +647,176 @@ msgstr "" 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:221 cps/templates/detail.html:41 -#: cps/templates/detail.html:45 -msgid "Send to Kindle" +#: 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:115 cps/helper.py:223 -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 "" -#: cps/helper.py:113 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:114 -msgid "Test e-mail" +#: cps/helper.py:116 +msgid "Test Email" msgstr "" -#: cps/helper.py:131 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:136 +#: 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:147 cps/helper.py:153 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to Kindle" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:172 cps/helper.py:176 cps/helper.py:180 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to Kindle" +msgid "Send %(format)s to eReader" msgstr "" -#: cps/helper.py:220 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to Kindle" +msgid "%(book)s send to eReader" msgstr "" -#: cps/helper.py:225 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "" -#: cps/helper.py:353 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:376 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:382 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:393 +#: 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:458 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:529 cps/helper.py:538 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "" -#: cps/helper.py:572 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:592 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:610 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "" -#: cps/helper.py:651 cps/web.py:1737 -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:659 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:669 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" msgstr "" -#: cps/helper.py:754 -msgid "Python modul 'advocate' is not installed but is needed for cover downloads" +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:767 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:770 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:773 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:783 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:799 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:810 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:822 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:826 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:878 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:889 -msgid "Error excecuting UnRar" -msgstr "" - -#: cps/helper.py:937 -msgid "Waiting" -msgstr "" - -#: cps/helper.py:939 -msgid "Failed" -msgstr "" - -#: cps/helper.py:941 -msgid "Started" +#: cps/helper.py:984 +msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:943 -msgid "Finished" +#: cps/helper.py:1077 +msgid "Cover" msgstr "" -#: cps/helper.py:945 -msgid "Unknown Status" +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:128 +#: 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:154 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -794,9 +825,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1613 +#: 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 @@ -855,12 +886,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:298 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:84 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1662 +#: 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 "" @@ -876,494 +908,597 @@ msgstr "" msgid "Success! Please return to your device" msgstr "" -#: cps/render_template.py:41 cps/web.py:407 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:43 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "" -#: cps/render_template.py:44 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "" -#: cps/render_template.py:46 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "" -#: cps/render_template.py:48 cps/render_template.py:53 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:50 cps/render_template.py:55 +#: 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:58 cps/templates/index.xml:32 cps/web.py:422 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "" -#: cps/render_template.py:60 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:61 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:729 +#: 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:63 -msgid "Show read and unread" +#: cps/render_template.py:64 +msgid "Show Read and Unread" msgstr "" -#: cps/render_template.py:65 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:732 +#: 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:67 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:68 +#: cps/render_template.py:69 msgid "Discover" msgstr "" -#: cps/render_template.py:70 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:71 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1135 +#: 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:73 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:74 cps/templates/book_edit.html:90 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:1034 cps/web.py:1041 +#: 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:76 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:77 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:79 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:81 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:1006 +#: 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:83 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:84 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1108 +#: 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:87 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:88 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:90 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:91 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:93 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:95 cps/web.py:755 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:97 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:100 cps/web.py:837 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:102 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/shelf.py:67 cps/shelf.py:121 +#: 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 "" + +#: cps/search.py:188 +msgid "Published after " +msgstr "" + +#: cps/search.py:195 +msgid "Published before " +msgstr "" + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "" + +#: cps/search.py:221 +#, python-format +msgid "Read Status = '%(status)s'" +msgstr "" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "" + +#: cps/shelf.py:49 cps/shelf.py:103 msgid "Invalid shelf specified" msgstr "" -#: cps/shelf.py:73 +#: cps/shelf.py:55 msgid "Sorry you are not allowed to add a book to that shelf" msgstr "" -#: cps/shelf.py:82 +#: cps/shelf.py:64 #, python-format msgid "Book is already part of the shelf: %(shelfname)s" msgstr "" -#: cps/shelf.py:107 +#: cps/shelf.py:89 #, python-format msgid "Book has been added to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:126 +#: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" msgstr "" -#: cps/shelf.py:144 +#: cps/shelf.py:126 #, python-format msgid "Books are already part of the shelf: %(name)s" msgstr "" -#: cps/shelf.py:156 +#: cps/shelf.py:138 #, python-format msgid "Books have been added to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:163 +#: cps/shelf.py:145 #, python-format msgid "Could not add books to shelf: %(sname)s" msgstr "" -#: cps/shelf.py:209 +#: cps/shelf.py:191 #, python-format msgid "Book has been removed from shelf: %(sname)s" msgstr "" -#: cps/shelf.py:218 +#: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:228 cps/templates/layout.html:140 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "" -#: cps/shelf.py:236 +#: cps/shelf.py:218 msgid "Sorry you are not allowed to edit this shelf" msgstr "" -#: cps/shelf.py:238 +#: cps/shelf.py:220 msgid "Edit a shelf" msgstr "" -#: cps/shelf.py:248 +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "" + +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:265 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "" -#: cps/shelf.py:268 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "" -#: cps/shelf.py:282 +#: cps/shelf.py:350 msgid "There was an error" msgstr "" -#: cps/shelf.py:304 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:315 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:337 -msgid "Error deleting Shelf" +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" msgstr "" -#: cps/shelf.py:339 -msgid "Shelf successfully deleted" +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "" -#: cps/shelf.py:389 -#, python-format -msgid "Change order of Shelf: '%(name)s'" +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" msgstr "" -#: cps/shelf.py:461 -#, python-format -msgid "Shelf: '%(name)s'" +#: cps/tasks_status.py:62 +msgid "Waiting" msgstr "" -#: cps/shelf.py:465 -msgid "Error opening shelf. Shelf does not exist or is not accessible" +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "" + +#: cps/tasks_status.py:70 +msgid "Ended" msgstr "" -#: cps/updater.py:426 cps/updater.py:437 cps/updater.py:538 cps/updater.py:553 +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "" + +#: 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 "" -#: cps/updater.py:433 cps/updater.py:545 +#: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" msgstr "" -#: cps/updater.py:451 +#: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." msgstr "" -#: cps/updater.py:469 +#: cps/updater.py:474 msgid "Could not fetch update information" msgstr "" -#: cps/updater.py:479 +#: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." msgstr "" -#: cps/updater.py:488 cps/updater.py:502 cps/updater.py:513 +#: 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 "" -#: cps/updater.py:531 +#: cps/updater.py:536 msgid "No release information available" msgstr "" -#: cps/templates/index.html:5 cps/web.py:434 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "" -#: cps/web.py:470 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "" -#: cps/web.py:501 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:534 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:570 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "" -#: cps/web.py:598 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "" -#: cps/web.py:610 +#: cps/web.py:620 +msgid "Rating: None" +msgstr "" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:626 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:663 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "" -#: cps/web.py:690 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "" -#: cps/templates/layout.html:56 cps/web.py:789 cps/web.py:1444 -msgid "Advanced Search" -msgstr "" - -#: cps/templates/book_edit.html:235 cps/templates/feed.xml:33 -#: cps/templates/index.xml:11 cps/templates/layout.html:45 -#: cps/templates/layout.html:48 cps/templates/search_form.html:226 -#: cps/web.py:807 cps/web.py:1164 -msgid "Search" -msgstr "" - -#: cps/templates/admin.html:16 cps/web.py:979 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "" -#: cps/web.py:1068 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1095 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/templates/layout.html:73 cps/templates/tasks.html:7 cps/web.py:1149 -msgid "Tasks" -msgstr "" - -#: cps/web.py:1286 -msgid "Published after " -msgstr "" - -#: cps/web.py:1293 -msgid "Published before " -msgstr "" - -#: cps/web.py:1315 -#, python-format -msgid "Rating <= %(rating)s" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." msgstr "" -#: cps/web.py:1317 +#: cps/web.py:1240 #, python-format -msgid "Rating >= %(rating)s" +msgid "Success! Book queued for sending to %(eReadermail)s" msgstr "" -#: cps/web.py:1319 +#: cps/web.py:1243 #, python-format -msgid "Read Status = %(status)s" +msgid "Oops! There was an error sending book: %(res)s" msgstr "" -#: cps/web.py:1425 -msgid "Error on search for custom columns, please restart Calibre-Web" +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1527 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/web.py:1531 -#, python-format -msgid "Oops! There was an error sending this book: %(res)s" +#: 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:1533 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "" -#: cps/web.py:1550 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "" -#: cps/templates/layout.html:85 cps/templates/register.html:17 cps/web.py:1551 -#: cps/web.py:1558 cps/web.py:1564 cps/web.py:1583 cps/web.py:1587 -#: cps/web.py:1593 -msgid "Register" +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "" -#: cps/web.py:1585 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1348 cps/web.py:1366 +msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1588 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1360 +msgid "Please wait one minute before next login" msgstr "" -#: cps/web.py:1602 -msgid "Cannot activate LDAP authentication" +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" msgstr "" -#: cps/web.py:1621 +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1627 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1631 cps/web.py:1656 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "" -#: cps/web.py:1638 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1644 +#: 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:1651 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" msgstr "" -#: cps/web.py:1717 cps/web.py:1766 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" +msgstr "" + +#: cps/web.py:1487 +msgid "Success! Profile Updated" msgstr "" -#: cps/web.py:1733 -msgid "Profile updated" +#: 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:154 +#: 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" msgstr "" -#: cps/tasks/convert.py:187 +#: cps/tasks/convert.py:186 #, python-format msgid "%(format)s format not found on disk" msgstr "" -#: cps/tasks/convert.py:191 +#: cps/tasks/convert.py:190 msgid "Ebook converter failed with unknown error" msgstr "" -#: cps/tasks/convert.py:201 +#: cps/tasks/convert.py:202 #, python-format msgid "Kepubify-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:223 +#: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" msgstr "" -#: cps/tasks/convert.py:246 +#: cps/tasks/convert.py:247 #, python-format msgid "Ebook-converter failed: %(error)s" msgstr "" -#: cps/tasks/convert.py:269 +#: cps/tasks/convert.py:270 #, python-format msgid "Calibre failed with error: %(error)s" msgstr "" +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "" + +#: 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:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "" + #: cps/templates/admin.html:9 msgid "Users" msgstr "" @@ -1376,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 Kindle E-mail Address" +msgid "Send to eReader Email" msgstr "" -#: cps/templates/admin.html:17 cps/templates/layout.html:76 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "" @@ -1393,13 +1528,8 @@ msgstr "" msgid "Password" msgstr "" -#: cps/templates/admin.html:20 cps/templates/layout.html:66 -#: cps/templates/user_table.html:145 -msgid "Upload" -msgstr "" - -#: cps/templates/admin.html:22 cps/templates/detail.html:18 -#: cps/templates/detail.html:27 cps/templates/shelf.html:7 +#: 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 "" @@ -1413,7 +1543,7 @@ msgstr "" msgid "Edit" msgstr "" -#: cps/templates/admin.html:25 cps/templates/book_edit.html:16 +#: 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 @@ -1424,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 @@ -1454,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 @@ -1525,78 +1651,109 @@ msgstr "" msgid "Edit UI Configuration" msgstr "" -#: cps/templates/admin.html:166 -msgid "Administration" +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" msgstr "" -#: cps/templates/admin.html:167 -msgid "Download Debug Package" +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" -#: cps/templates/admin.html:168 -msgid "View Logs" +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:171 +#: 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/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:172 +#: 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:173 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:178 -msgid "Update" +#: cps/templates/admin.html:221 +msgid "Version Information" msgstr "" -#: cps/templates/admin.html:182 +#: cps/templates/admin.html:225 msgid "Version" msgstr "" -#: cps/templates/admin.html:183 +#: cps/templates/admin.html:226 msgid "Details" msgstr "" -#: cps/templates/admin.html:189 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "" -#: cps/templates/admin.html:196 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "" -#: cps/templates/admin.html:197 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "" -#: cps/templates/admin.html:210 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:215 cps/templates/admin.html:229 -#: cps/templates/admin.html:249 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:216 cps/templates/admin.html:230 -#: cps/templates/book_edit.html:213 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: 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/shelf_edit.html:27 +#: 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:228 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:240 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "" @@ -1608,39 +1765,39 @@ msgstr "" msgid "In Library" msgstr "" -#: cps/templates/author.html:26 cps/templates/index.html:73 -#: cps/templates/search.html:30 cps/templates/shelf.html:19 +#: 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 "" -#: cps/templates/author.html:27 cps/templates/index.html:74 -#: cps/templates/search.html:31 cps/templates/shelf.html:20 +#: 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 "" -#: cps/templates/author.html:28 cps/templates/index.html:75 -#: cps/templates/search.html:32 cps/templates/shelf.html:21 +#: 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 "" -#: cps/templates/author.html:29 cps/templates/index.html:76 -#: cps/templates/search.html:33 cps/templates/shelf.html:22 +#: 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 "" -#: cps/templates/author.html:30 cps/templates/index.html:79 -#: cps/templates/search.html:36 cps/templates/shelf.html:25 +#: 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 "" -#: cps/templates/author.html:31 cps/templates/index.html:80 -#: cps/templates/search.html:37 cps/templates/shelf.html:26 +#: 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 "" #: cps/templates/author.html:56 cps/templates/author.html:115 -#: cps/templates/index.html:29 cps/templates/index.html:112 -#: cps/templates/search.html:66 cps/templates/shelf.html:54 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 msgid "reduce" msgstr "" @@ -1648,164 +1805,165 @@ msgstr "" msgid "More by" msgstr "" -#: cps/templates/book_edit.html:10 +#: cps/templates/book_edit.html:11 msgid "Delete Book" msgstr "" -#: cps/templates/book_edit.html:13 +#: cps/templates/book_edit.html:14 msgid "Delete formats:" msgstr "" -#: cps/templates/book_edit.html:24 +#: cps/templates/book_edit.html:25 msgid "Convert book format:" msgstr "" -#: cps/templates/book_edit.html:29 +#: cps/templates/book_edit.html:30 msgid "Convert from:" msgstr "" -#: cps/templates/book_edit.html:31 cps/templates/book_edit.html:38 +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" msgstr "" -#: cps/templates/book_edit.html:36 +#: cps/templates/book_edit.html:37 msgid "Convert to:" msgstr "" -#: cps/templates/book_edit.html:45 +#: cps/templates/book_edit.html:46 msgid "Convert book" msgstr "" -#: cps/templates/book_edit.html:55 cps/templates/search_form.html:8 +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 msgid "Book Title" msgstr "" -#: cps/templates/book_edit.html:62 cps/templates/book_edit.html:270 -#: cps/templates/book_edit.html:288 cps/templates/search_form.html:12 +#: 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 "" -#: cps/templates/book_edit.html:67 cps/templates/book_edit.html:275 -#: cps/templates/book_edit.html:290 cps/templates/search_form.html:153 +#: 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 "" -#: cps/templates/book_edit.html:72 +#: cps/templates/book_edit.html:73 msgid "Identifiers" msgstr "" -#: cps/templates/book_edit.html:76 cps/templates/book_edit.html:299 +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 msgid "Identifier Type" msgstr "" -#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 msgid "Identifier Value" msgstr "" -#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 #: cps/templates/user_table.html:24 msgid "Remove" msgstr "" -#: cps/templates/book_edit.html:82 +#: cps/templates/book_edit.html:83 msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:86 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "" -#: cps/templates/book_edit.html:94 +#: cps/templates/book_edit.html:95 msgid "Series ID" msgstr "" -#: cps/templates/book_edit.html:98 +#: cps/templates/book_edit.html:99 msgid "Rating" msgstr "" -#: cps/templates/book_edit.html:103 +#: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" msgstr "" -#: cps/templates/book_edit.html:107 +#: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" msgstr "" -#: cps/templates/book_edit.html:112 +#: cps/templates/book_edit.html:113 msgid "Published Date" msgstr "" -#: cps/templates/book_edit.html:121 cps/templates/book_edit.html:272 -#: cps/templates/book_edit.html:289 cps/templates/detail.html:164 -#: cps/templates/search_form.html:16 +#: 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 "" -#: cps/templates/book_edit.html:125 cps/templates/detail.html:131 -#: 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:135 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:136 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 "" -#: cps/templates/book_edit.html:200 +#: cps/templates/book_edit.html:201 msgid "Upload Format" msgstr "" -#: cps/templates/book_edit.html:208 +#: cps/templates/book_edit.html:209 msgid "View Book on Save" msgstr "" -#: cps/templates/book_edit.html:211 cps/templates/book_edit.html:229 +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" msgstr "" -#: cps/templates/book_edit.html:212 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/shelf_edit.html:25 -#: cps/templates/shelf_order.html:41 cps/templates/user_edit.html:142 +#: 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 "" -#: cps/templates/book_edit.html:232 +#: cps/templates/book_edit.html:233 msgid "Keyword" msgstr "" -#: cps/templates/book_edit.html:233 +#: cps/templates/book_edit.html:234 msgid "Search keyword" msgstr "" -#: cps/templates/book_edit.html:239 +#: cps/templates/book_edit.html:240 msgid "Click the cover to load metadata to the form" msgstr "" -#: cps/templates/book_edit.html:246 cps/templates/book_edit.html:285 +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 msgid "Loading..." msgstr "" -#: cps/templates/book_edit.html:250 cps/templates/layout.html:63 -#: cps/templates/layout.html:186 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 "" -#: cps/templates/book_edit.html:277 cps/templates/book_edit.html:291 +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 msgid "Source" msgstr "" -#: cps/templates/book_edit.html:286 +#: cps/templates/book_edit.html:287 msgid "Search error!" msgstr "" -#: cps/templates/book_edit.html:287 +#: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." msgstr "" @@ -1897,7 +2055,7 @@ msgid "Comments" msgstr "" #: cps/templates/book_table.html:75 -msgid "Archiv Status" +msgid "Archive Status" msgstr "" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 @@ -1912,6 +2070,7 @@ 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 "" @@ -2016,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 @@ -2032,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 @@ -2222,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 "" @@ -2234,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 "" @@ -2323,79 +2526,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:60 cps/templates/detail.html:69 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "" -#: cps/templates/detail.html:77 cps/templates/detail.html:94 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:124 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:173 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "" -#: cps/templates/detail.html:221 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:231 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:243 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "" -#: cps/templates/detail.html:256 cps/templates/search.html:15 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "" -#: cps/templates/detail.html:267 cps/templates/detail.html:284 -#: cps/templates/feed.xml:79 cps/templates/layout.html:137 -#: cps/templates/search.html:21 +#: 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:298 +#: 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 @@ -2419,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:29 +#: 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 "" @@ -2448,186 +2653,194 @@ msgstr "" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:170 +#: 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 msgid "Kobo Token:" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: 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 "" -#: cps/templates/index.html:70 +#: cps/templates/index.html:71 msgid "Sort ascending according to download count" msgstr "" -#: cps/templates/index.html:71 +#: cps/templates/index.html:72 msgid "Sort descending according to download count" msgstr "" -#: cps/templates/index.html:77 cps/templates/search.html:34 -#: cps/templates/shelf.html:23 +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 msgid "Sort authors in alphabetical order" msgstr "" -#: cps/templates/index.html:78 cps/templates/search.html:35 -#: cps/templates/shelf.html:24 +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 msgid "Sort authors in reverse alphabetical order" msgstr "" -#: cps/templates/index.html:82 +#: cps/templates/index.html:83 msgid "Sort ascending according to series index" msgstr "" -#: cps/templates/index.html:83 +#: cps/templates/index.html:84 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:135 -#: 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:29 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:35 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "" -#: cps/templates/layout.html:46 +#: cps/templates/layout.html:47 msgid "Search Library" msgstr "" -#: cps/templates/layout.html:63 cps/templates/layout.html:117 -msgid "Uploading..." +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" msgstr "" -#: cps/templates/layout.html:63 -msgid "Error" +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" msgstr "" -#: cps/templates/layout.html:63 -msgid "Upload done, processing, please wait..." +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." msgstr "" -#: cps/templates/layout.html:76 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" +#: cps/templates/layout.html:78 +msgid "Error" msgstr "" #: cps/templates/layout.html:78 -msgid "Account" +msgid "Upload done, processing, please wait..." msgstr "" -#: cps/templates/layout.html:80 -msgid "Logout" +#: 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:118 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:128 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "" -#: cps/templates/layout.html:141 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "" -#: cps/templates/layout.html:155 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "" -#: cps/templates/layout.html:182 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "" +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + #: cps/templates/login.html:18 msgid "Remember Me" msgstr "" @@ -2636,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 "" @@ -2732,7 +2945,7 @@ msgstr "" msgid "Select" msgstr "" -#: cps/templates/modal_dialogs.html:134 +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" msgstr "" @@ -2744,127 +2957,159 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:75 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "" + +#: 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/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:116 -msgid "Light" +#: cps/templates/readcbr.html:110 +msgid "Display" msgstr "" -#: cps/templates/readcbr.html:117 -msgid "Dark" +#: cps/templates/readcbr.html:113 +msgid "Single Page" msgstr "" -#: cps/templates/readcbr.html:122 +#: 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 "" @@ -2872,7 +3117,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -2889,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 @@ -2908,15 +3153,19 @@ msgstr "" msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/search.html:5 -msgid "No Results Found" +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" msgstr "" #: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "" + +#: cps/templates/search.html:7 msgid "Search Term:" msgstr "" -#: cps/templates/search.html:8 +#: cps/templates/search.html:9 msgid "Results for:" msgstr "" @@ -2928,63 +3177,71 @@ 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 "" -#: cps/templates/shelf.html:12 +#: cps/templates/shelf.html:13 msgid "Delete this Shelf" msgstr "" -#: cps/templates/shelf.html:13 +#: cps/templates/shelf.html:14 msgid "Edit Shelf Properties" msgstr "" -#: cps/templates/shelf.html:16 +#: cps/templates/shelf.html:17 msgid "Arrange books manually" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Disable Change order" msgstr "" -#: cps/templates/shelf.html:17 +#: cps/templates/shelf.html:18 msgid "Enable Change order" msgstr "" @@ -3029,7 +3286,7 @@ msgid "System Statistics" msgstr "" #: cps/templates/stats.html:33 -msgid "Program Library" +msgid "Program" msgstr "" #: cps/templates/stats.html:34 @@ -3056,8 +3313,16 @@ msgstr "" msgid "Run Time" msgstr "" -#: cps/templates/tasks.html:18 -msgid "Start Time" +#: 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 "" + +#: 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 @@ -3121,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 Kindle E-mail Address" +msgid "Enter eReader Email" msgstr "" #: cps/templates/user_table.html:136 -msgid "Kindle E-mail" +msgid "eReader Email" msgstr "" #: cps/templates/user_table.html:137 @@ -3189,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 4360d221..6763eaff 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -1,44 +1,45 @@ # 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 -scholarly>=1.2.0,<1.7 +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.11.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.5.0 +jsonschema>=3.2.0,<4.20.0 diff --git a/requirements.txt b/requirements.txt index 7a30ae06..c28f2019 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.1 +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 -PyPDF3>=1.0.0,<1.0.7 +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.1.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 aff22e9e..eb73462d 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.1 + 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 - PyPDF3>=1.0.0,<1.0.7 + 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.1.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 +[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.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 = 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.7 + 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.11.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.5.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 027aaa81..6bafbd11 100644 --- a/test/Calibre-Web TestSummary_Linux.html +++ b/test/Calibre-Web TestSummary_Linux.html @@ -37,20 +37,20 @@
-

Start Time: 2022-04-30 21:05:13

+

Start Time: 2024-01-17 20:30:42

-

Stop Time: 2022-05-01 02:54:00

+

Stop Time: 2024-01-18 03:25:01

-

Duration: 4h 55 min

+

Duration: 5h 47 min

@@ -234,21 +234,465 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + @@ -257,7 +701,7 @@ - + @@ -266,7 +710,7 @@ - + @@ -275,7 +719,7 @@ - + @@ -284,7 +728,7 @@ - + @@ -293,7 +737,7 @@ - + @@ -302,7 +746,7 @@ - + @@ -311,7 +755,16 @@ - + + + + + + + + @@ -320,7 +773,16 @@ - + + + + + + + + @@ -329,7 +791,7 @@ - + @@ -337,6 +799,15 @@ + + + + + + + @@ -347,13 +818,13 @@ - + @@ -362,7 +833,7 @@ - + @@ -371,7 +842,7 @@ - + @@ -380,7 +851,7 @@ - + @@ -398,13 +869,13 @@ - + @@ -413,7 +884,7 @@ - + @@ -431,13 +902,13 @@ - + @@ -455,13 +926,13 @@ - + @@ -470,7 +941,7 @@ - + @@ -479,7 +950,7 @@ - + @@ -488,7 +959,7 @@ - + @@ -497,7 +968,7 @@ - + @@ -506,7 +977,7 @@ - + @@ -515,7 +986,7 @@ - + @@ -524,7 +995,7 @@ - + @@ -533,7 +1004,7 @@ - + @@ -542,7 +1013,7 @@ - + @@ -551,7 +1022,7 @@ - + @@ -560,7 +1031,7 @@ - + @@ -569,7 +1040,7 @@ - + @@ -578,7 +1049,7 @@ - + @@ -587,7 +1058,7 @@ - + @@ -597,21 +1068,21 @@ - + - - + + - + @@ -620,7 +1091,7 @@ - + @@ -629,7 +1100,7 @@ - + @@ -638,7 +1109,7 @@ - + @@ -647,7 +1118,7 @@ - + @@ -656,7 +1127,7 @@ - + @@ -664,35 +1135,6 @@ - - - - - - - @@ -703,13 +1145,13 @@ AssertionError: 20 != 0 - + @@ -718,7 +1160,7 @@ AssertionError: 20 != 0 - + @@ -727,7 +1169,7 @@ AssertionError: 20 != 0 - + @@ -745,13 +1187,13 @@ AssertionError: 20 != 0 - + @@ -760,7 +1202,7 @@ AssertionError: 20 != 0 - + @@ -769,7 +1211,7 @@ AssertionError: 20 != 0 - + @@ -781,19 +1223,19 @@ AssertionError: 20 != 0 - - + + - + - + @@ -802,7 +1244,7 @@ AssertionError: 20 != 0 - + @@ -811,7 +1253,7 @@ AssertionError: 20 != 0 - + @@ -820,7 +1262,7 @@ AssertionError: 20 != 0 - + @@ -829,7 +1271,7 @@ AssertionError: 20 != 0 - + @@ -838,88 +1280,132 @@ AssertionError: 20 != 0 - + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + + - - + - + @@ -928,7 +1414,7 @@ AssertionError: 20 != 0 - + @@ -937,7 +1423,7 @@ AssertionError: 20 != 0 - + @@ -949,19 +1435,19 @@ AssertionError: 20 != 0 + - - + - + @@ -970,7 +1456,7 @@ AssertionError: 20 != 0 - + @@ -979,7 +1465,7 @@ AssertionError: 20 != 0 - + @@ -988,7 +1474,7 @@ AssertionError: 20 != 0 - + @@ -997,7 +1483,7 @@ AssertionError: 20 != 0 - + @@ -1006,7 +1492,7 @@ AssertionError: 20 != 0 - + @@ -1015,7 +1501,7 @@ AssertionError: 20 != 0 - + @@ -1024,7 +1510,7 @@ AssertionError: 20 != 0 - + @@ -1033,7 +1519,7 @@ AssertionError: 20 != 0 - + @@ -1042,7 +1528,7 @@ AssertionError: 20 != 0 - + @@ -1051,7 +1537,7 @@ AssertionError: 20 != 0 - + @@ -1060,7 +1546,7 @@ AssertionError: 20 != 0 - + @@ -1069,7 +1555,7 @@ AssertionError: 20 != 0 - + @@ -1078,7 +1564,7 @@ AssertionError: 20 != 0 - + @@ -1087,7 +1573,7 @@ AssertionError: 20 != 0 - + @@ -1096,7 +1582,7 @@ AssertionError: 20 != 0 - + @@ -1105,7 +1591,7 @@ AssertionError: 20 != 0 - + @@ -1114,7 +1600,7 @@ AssertionError: 20 != 0 - + @@ -1123,7 +1609,7 @@ AssertionError: 20 != 0 - + @@ -1132,19 +1618,45 @@ AssertionError: 20 != 0 - + + + + + + + + + @@ -1167,7 +1679,7 @@ AssertionError: 20 != 0 - + @@ -1176,7 +1688,7 @@ AssertionError: 20 != 0 - + @@ -1185,7 +1697,7 @@ AssertionError: 20 != 0 - + @@ -1194,7 +1706,7 @@ AssertionError: 20 != 0 - + @@ -1203,7 +1715,7 @@ AssertionError: 20 != 0 - + @@ -1212,7 +1724,16 @@ AssertionError: 20 != 0 - + + + + + + + + @@ -1221,7 +1742,7 @@ AssertionError: 20 != 0 - + @@ -1230,7 +1751,7 @@ AssertionError: 20 != 0 - + @@ -1239,7 +1760,7 @@ AssertionError: 20 != 0 - + @@ -1248,7 +1769,7 @@ AssertionError: 20 != 0 - + @@ -1257,7 +1778,7 @@ AssertionError: 20 != 0 - + @@ -1266,7 +1787,7 @@ AssertionError: 20 != 0 - + @@ -1275,7 +1796,7 @@ AssertionError: 20 != 0 - + @@ -1284,7 +1805,7 @@ AssertionError: 20 != 0 - + @@ -1293,7 +1814,7 @@ AssertionError: 20 != 0 - + @@ -1311,13 +1832,13 @@ AssertionError: 20 != 0 - + @@ -1326,7 +1847,7 @@ AssertionError: 20 != 0 - + @@ -1335,7 +1856,7 @@ AssertionError: 20 != 0 - + @@ -1344,7 +1865,7 @@ AssertionError: 20 != 0 - + @@ -1353,7 +1874,7 @@ AssertionError: 20 != 0 - + @@ -1362,7 +1883,7 @@ AssertionError: 20 != 0 - + @@ -1380,13 +1901,13 @@ AssertionError: 20 != 0 - + @@ -1395,7 +1916,7 @@ AssertionError: 20 != 0 - + @@ -1404,7 +1925,7 @@ AssertionError: 20 != 0 - + @@ -1413,7 +1934,7 @@ AssertionError: 20 != 0 - + @@ -1422,7 +1943,7 @@ AssertionError: 20 != 0 - + @@ -1431,7 +1952,7 @@ AssertionError: 20 != 0 - + @@ -1449,13 +1970,13 @@ AssertionError: 20 != 0 - + @@ -1464,7 +1985,7 @@ AssertionError: 20 != 0 - + @@ -1473,7 +1994,7 @@ AssertionError: 20 != 0 - + @@ -1482,7 +2003,7 @@ AssertionError: 20 != 0 - + @@ -1491,7 +2012,7 @@ AssertionError: 20 != 0 - + @@ -1500,7 +2021,7 @@ AssertionError: 20 != 0 - + @@ -1509,7 +2030,7 @@ AssertionError: 20 != 0 - + @@ -1518,7 +2039,7 @@ AssertionError: 20 != 0 - + @@ -1527,7 +2048,7 @@ AssertionError: 20 != 0 - + @@ -1536,7 +2057,7 @@ AssertionError: 20 != 0 - + @@ -1545,7 +2066,7 @@ AssertionError: 20 != 0 - + @@ -1554,7 +2075,7 @@ AssertionError: 20 != 0 - + @@ -1563,7 +2084,7 @@ AssertionError: 20 != 0 - + @@ -1572,7 +2093,7 @@ AssertionError: 20 != 0 - + @@ -1581,7 +2102,7 @@ AssertionError: 20 != 0 - + @@ -1590,7 +2111,7 @@ AssertionError: 20 != 0 - + @@ -1599,7 +2120,7 @@ AssertionError: 20 != 0 - + @@ -1608,7 +2129,7 @@ AssertionError: 20 != 0 - + @@ -1618,25 +2139,45 @@ AssertionError: 20 != 0 - + - + - + - + @@ -1650,13 +2191,13 @@ AssertionError: 20 != 0 - + @@ -1665,7 +2206,7 @@ AssertionError: 20 != 0 - + @@ -1674,7 +2215,7 @@ AssertionError: 20 != 0 - + @@ -1683,7 +2224,7 @@ AssertionError: 20 != 0 - + @@ -1692,7 +2233,7 @@ AssertionError: 20 != 0 - + @@ -1701,7 +2242,7 @@ AssertionError: 20 != 0 - + @@ -1710,7 +2251,7 @@ AssertionError: 20 != 0 - + @@ -1719,7 +2260,7 @@ AssertionError: 20 != 0 - + @@ -1728,7 +2269,7 @@ AssertionError: 20 != 0 - + @@ -1737,7 +2278,7 @@ AssertionError: 20 != 0 - + @@ -1746,7 +2287,7 @@ AssertionError: 20 != 0 - + @@ -1755,7 +2296,7 @@ AssertionError: 20 != 0 - + @@ -1764,7 +2305,7 @@ AssertionError: 20 != 0 - + @@ -1773,7 +2314,7 @@ AssertionError: 20 != 0 - + @@ -1782,7 +2323,7 @@ AssertionError: 20 != 0 - + @@ -1791,7 +2332,7 @@ AssertionError: 20 != 0 - + @@ -1800,7 +2341,7 @@ AssertionError: 20 != 0 - + @@ -1809,7 +2350,7 @@ AssertionError: 20 != 0 - + @@ -1827,13 +2368,13 @@ AssertionError: 20 != 0 - + @@ -1851,13 +2392,13 @@ AssertionError: 20 != 0 - + @@ -1866,7 +2407,7 @@ AssertionError: 20 != 0 - + @@ -1875,7 +2416,7 @@ AssertionError: 20 != 0 - + @@ -1883,79 +2424,190 @@ AssertionError: 20 != 0 - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + - + - + - + - + @@ -1971,13 +2623,13 @@ AssertionError: 20 != 0 - + @@ -1995,13 +2647,13 @@ AssertionError: 20 != 0 - + @@ -2010,7 +2662,7 @@ AssertionError: 20 != 0 - + @@ -2028,13 +2680,13 @@ AssertionError: 20 != 0 - + @@ -2043,19 +2695,19 @@ AssertionError: 20 != 0 - + + @@ -2087,13 +2739,13 @@ AssertionError: 20 != 0 - + @@ -2111,13 +2763,13 @@ AssertionError: 20 != 0 - + @@ -2126,7 +2778,7 @@ AssertionError: 20 != 0 - + @@ -2135,7 +2787,7 @@ AssertionError: 20 != 0 - + @@ -2147,19 +2799,19 @@ AssertionError: 20 != 0 - - + + - + @@ -2168,7 +2820,7 @@ AssertionError: 20 != 0 - + @@ -2177,25 +2829,34 @@ AssertionError: 20 != 0 - + + + + + + + + - + - + @@ -2204,7 +2865,7 @@ AssertionError: 20 != 0 - + @@ -2213,7 +2874,7 @@ AssertionError: 20 != 0 - + @@ -2222,7 +2883,7 @@ AssertionError: 20 != 0 - + @@ -2231,7 +2892,7 @@ AssertionError: 20 != 0 - + @@ -2240,7 +2901,7 @@ AssertionError: 20 != 0 - + @@ -2249,7 +2910,7 @@ AssertionError: 20 != 0 - + @@ -2267,13 +2928,13 @@ AssertionError: 20 != 0 - + @@ -2282,7 +2943,7 @@ AssertionError: 20 != 0 - + @@ -2291,7 +2952,7 @@ AssertionError: 20 != 0 - + @@ -2300,7 +2961,7 @@ AssertionError: 20 != 0 - + @@ -2309,7 +2970,7 @@ AssertionError: 20 != 0 - + @@ -2318,7 +2979,7 @@ AssertionError: 20 != 0 - + @@ -2336,13 +2997,13 @@ AssertionError: 20 != 0 - + @@ -2351,7 +3012,7 @@ AssertionError: 20 != 0 - + @@ -2360,7 +3021,7 @@ AssertionError: 20 != 0 - + @@ -2369,7 +3030,7 @@ AssertionError: 20 != 0 - + @@ -2378,7 +3039,7 @@ AssertionError: 20 != 0 - + @@ -2387,7 +3048,7 @@ AssertionError: 20 != 0 - + @@ -2396,7 +3057,7 @@ AssertionError: 20 != 0 - + @@ -2405,7 +3066,7 @@ AssertionError: 20 != 0 - + @@ -2414,7 +3075,7 @@ AssertionError: 20 != 0 - + @@ -2423,7 +3084,7 @@ AssertionError: 20 != 0 - + @@ -2432,7 +3093,7 @@ AssertionError: 20 != 0 - + @@ -2441,7 +3102,7 @@ AssertionError: 20 != 0 - + @@ -2450,7 +3111,7 @@ AssertionError: 20 != 0 - + @@ -2460,6 +3121,57 @@ AssertionError: 20 != 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2468,13 +3180,13 @@ AssertionError: 20 != 0 - + @@ -2483,7 +3195,7 @@ AssertionError: 20 != 0 - + @@ -2492,7 +3204,7 @@ AssertionError: 20 != 0 - + @@ -2501,7 +3213,7 @@ AssertionError: 20 != 0 - + @@ -2510,7 +3222,7 @@ AssertionError: 20 != 0 - + @@ -2519,7 +3231,7 @@ AssertionError: 20 != 0 - + @@ -2528,7 +3240,7 @@ AssertionError: 20 != 0 - + @@ -2537,7 +3249,7 @@ AssertionError: 20 != 0 - + @@ -2546,7 +3258,7 @@ AssertionError: 20 != 0 - + @@ -2555,7 +3267,7 @@ AssertionError: 20 != 0 - + @@ -2573,13 +3285,13 @@ AssertionError: 20 != 0 - + @@ -2588,7 +3300,7 @@ AssertionError: 20 != 0 - + @@ -2597,7 +3309,7 @@ AssertionError: 20 != 0 - + @@ -2606,7 +3318,7 @@ AssertionError: 20 != 0 - + @@ -2615,19 +3327,19 @@ AssertionError: 20 != 0 - + + @@ -2650,7 +3362,7 @@ AssertionError: 20 != 0 - + @@ -2659,7 +3371,7 @@ AssertionError: 20 != 0 - + @@ -2668,7 +3380,7 @@ AssertionError: 20 != 0 - + @@ -2678,21 +3390,21 @@ AssertionError: 20 != 0 - + - - - + + + - + @@ -2701,7 +3413,7 @@ AssertionError: 20 != 0 - + @@ -2710,7 +3422,7 @@ AssertionError: 20 != 0 - + @@ -2719,7 +3431,7 @@ AssertionError: 20 != 0 - + @@ -2728,7 +3440,7 @@ AssertionError: 20 != 0 - + @@ -2737,7 +3449,7 @@ AssertionError: 20 != 0 - + @@ -2746,7 +3458,16 @@ AssertionError: 20 != 0 - + + + + + + + + @@ -2755,7 +3476,7 @@ AssertionError: 20 != 0 - + @@ -2764,7 +3485,7 @@ AssertionError: 20 != 0 - + @@ -2773,7 +3494,7 @@ AssertionError: 20 != 0 - + @@ -2782,7 +3503,7 @@ AssertionError: 20 != 0 - + @@ -2791,7 +3512,7 @@ AssertionError: 20 != 0 - + @@ -2800,7 +3521,7 @@ AssertionError: 20 != 0 - + @@ -2809,7 +3530,16 @@ AssertionError: 20 != 0 - + + + + + + + + @@ -2818,7 +3548,45 @@ AssertionError: 20 != 0 - + + + + + + + + + + + + + + + @@ -2836,13 +3604,13 @@ AssertionError: 20 != 0 - + @@ -2851,7 +3619,7 @@ AssertionError: 20 != 0 - + @@ -2869,13 +3637,13 @@ AssertionError: 20 != 0 - + @@ -2884,7 +3652,7 @@ AssertionError: 20 != 0 - + @@ -2896,19 +3664,19 @@ AssertionError: 20 != 0 - - + + - + @@ -2917,7 +3685,7 @@ AssertionError: 20 != 0 - + @@ -2926,7 +3694,7 @@ AssertionError: 20 != 0 - + @@ -2935,7 +3703,7 @@ AssertionError: 20 != 0 - + @@ -2944,7 +3712,7 @@ AssertionError: 20 != 0 - + @@ -2953,7 +3721,7 @@ AssertionError: 20 != 0 - + @@ -2962,7 +3730,7 @@ AssertionError: 20 != 0 - + @@ -2971,7 +3739,7 @@ AssertionError: 20 != 0 - + @@ -2980,7 +3748,7 @@ AssertionError: 20 != 0 - + @@ -2989,7 +3757,7 @@ AssertionError: 20 != 0 - + @@ -2998,7 +3766,7 @@ AssertionError: 20 != 0 - + @@ -3007,7 +3775,7 @@ AssertionError: 20 != 0 - + @@ -3016,7 +3784,7 @@ AssertionError: 20 != 0 - + @@ -3025,7 +3793,7 @@ AssertionError: 20 != 0 - + @@ -3034,7 +3802,7 @@ AssertionError: 20 != 0 - + @@ -3043,7 +3811,7 @@ AssertionError: 20 != 0 - + @@ -3052,7 +3820,7 @@ AssertionError: 20 != 0 - + @@ -3061,7 +3829,7 @@ AssertionError: 20 != 0 - + @@ -3070,7 +3838,7 @@ AssertionError: 20 != 0 - + @@ -3079,7 +3847,16 @@ AssertionError: 20 != 0 - + + + + + + + + @@ -3088,7 +3865,7 @@ AssertionError: 20 != 0 - + @@ -3097,7 +3874,7 @@ AssertionError: 20 != 0 - + @@ -3106,7 +3883,7 @@ AssertionError: 20 != 0 - + @@ -3124,13 +3901,13 @@ AssertionError: 20 != 0 - + @@ -3148,13 +3925,13 @@ AssertionError: 20 != 0 - + @@ -3163,7 +3940,7 @@ AssertionError: 20 != 0 - + @@ -3172,7 +3949,7 @@ AssertionError: 20 != 0 - + @@ -3182,21 +3959,39 @@ AssertionError: 20 != 0 - + - - - + + + - + + + + + + + + + + + + + + + @@ -3205,7 +4000,7 @@ AssertionError: 20 != 0 - + @@ -3214,7 +4009,7 @@ AssertionError: 20 != 0 - + @@ -3223,42 +4018,27 @@ AssertionError: 20 != 0 - + - + - - - - - - - - - - - - - - + @@ -3267,22 +4047,22 @@ AssertionError: 20 != 0 - + - + @@ -3298,13 +4078,13 @@ AssertionError: 20 != 0 - + @@ -3313,7 +4093,7 @@ AssertionError: 20 != 0 - + @@ -3322,7 +4102,7 @@ AssertionError: 20 != 0 - + @@ -3331,7 +4111,7 @@ AssertionError: 20 != 0 - + @@ -3340,7 +4120,7 @@ AssertionError: 20 != 0 - + @@ -3349,7 +4129,7 @@ AssertionError: 20 != 0 - + @@ -3358,7 +4138,7 @@ AssertionError: 20 != 0 - + @@ -3367,7 +4147,7 @@ AssertionError: 20 != 0 - + @@ -3385,13 +4165,13 @@ AssertionError: 20 != 0 - + @@ -3400,7 +4180,7 @@ AssertionError: 20 != 0 - + @@ -3409,7 +4189,7 @@ AssertionError: 20 != 0 - + @@ -3427,13 +4207,13 @@ AssertionError: 20 != 0 - + @@ -3442,7 +4222,7 @@ AssertionError: 20 != 0 - + @@ -3451,7 +4231,7 @@ AssertionError: 20 != 0 - + @@ -3460,7 +4240,7 @@ AssertionError: 20 != 0 - + @@ -3469,7 +4249,7 @@ AssertionError: 20 != 0 - + @@ -3478,7 +4258,7 @@ AssertionError: 20 != 0 - + @@ -3487,7 +4267,7 @@ AssertionError: 20 != 0 - + @@ -3496,7 +4276,7 @@ AssertionError: 20 != 0 - + @@ -3505,7 +4285,7 @@ AssertionError: 20 != 0 - + @@ -3514,7 +4294,7 @@ AssertionError: 20 != 0 - + @@ -3523,7 +4303,7 @@ AssertionError: 20 != 0 - + @@ -3532,7 +4312,7 @@ AssertionError: 20 != 0 - + @@ -3541,7 +4321,7 @@ AssertionError: 20 != 0 - + @@ -3550,19 +4330,19 @@ AssertionError: 20 != 0 - + + @@ -3585,7 +4365,7 @@ AssertionError: 20 != 0 - + @@ -3595,6 +4375,54 @@ AssertionError: 20 != 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3603,13 +4431,13 @@ AssertionError: 20 != 0 - + @@ -3619,21 +4447,21 @@ AssertionError: 20 != 0 - + - - + + - + @@ -3642,7 +4470,7 @@ AssertionError: 20 != 0 - + @@ -3651,7 +4479,7 @@ AssertionError: 20 != 0 - + @@ -3660,36 +4488,16 @@ AssertionError: 20 != 0 - + - + - + @@ -3698,7 +4506,7 @@ AssertionError: 0.038404302739168276 not greater than or equal to 0.05 - + @@ -3707,7 +4515,7 @@ AssertionError: 0.038404302739168276 not greater than or equal to 0.05 - + @@ -3716,31 +4524,11 @@ AssertionError: 0.038404302739168276 not greater than or equal to 0.05 - + - + @@ -3754,13 +4542,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3769,7 +4557,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3778,7 +4566,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3787,7 +4575,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3796,7 +4584,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3805,7 +4593,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3814,19 +4602,19 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + + @@ -3849,7 +4637,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3861,19 +4649,28 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - - + + - + + + + + + + + @@ -3882,7 +4679,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3891,7 +4688,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3900,7 +4697,16 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + + + + + + + + @@ -3918,13 +4724,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3933,7 +4739,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3942,7 +4748,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3951,7 +4757,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3960,7 +4766,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3969,7 +4775,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3978,7 +4784,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3987,7 +4793,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -3996,7 +4802,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4005,7 +4811,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4014,7 +4820,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4023,7 +4829,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4032,7 +4838,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4041,7 +4847,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4050,7 +4856,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4059,7 +4865,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4068,7 +4874,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4077,7 +4883,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4095,13 +4901,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4119,13 +4925,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4134,7 +4940,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4143,7 +4949,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4152,7 +4958,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4161,7 +4967,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4170,7 +4976,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4179,7 +4985,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4188,7 +4994,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4197,7 +5003,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4206,7 +5012,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4215,7 +5021,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4224,7 +5030,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4233,7 +5039,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4242,7 +5048,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4251,7 +5057,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4260,7 +5066,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4269,7 +5075,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4278,7 +5084,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4287,7 +5093,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4296,7 +5102,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4305,7 +5111,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4323,13 +5129,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4338,7 +5144,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4347,7 +5153,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4356,7 +5162,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4365,7 +5171,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4374,7 +5180,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4383,7 +5189,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4392,7 +5198,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4401,7 +5207,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4410,7 +5216,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4419,7 +5225,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4428,7 +5234,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4437,7 +5243,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4446,7 +5252,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4455,7 +5261,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4464,7 +5270,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4473,7 +5279,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4482,7 +5288,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4491,7 +5297,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4500,7 +5306,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4509,7 +5315,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4518,7 +5324,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4527,7 +5333,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4536,7 +5342,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4545,7 +5351,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4554,7 +5360,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4563,7 +5369,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4572,7 +5378,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4581,7 +5387,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4590,7 +5396,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4599,7 +5405,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4608,7 +5414,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4617,7 +5423,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4626,7 +5432,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4635,7 +5441,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4653,13 +5459,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4668,7 +5474,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4677,7 +5483,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4686,7 +5492,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4695,7 +5501,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4704,7 +5510,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4713,7 +5519,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4722,7 +5528,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4731,7 +5537,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4740,7 +5546,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4749,7 +5555,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4758,7 +5564,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4767,7 +5573,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4776,7 +5582,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4785,7 +5591,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4794,7 +5600,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - + @@ -4805,11 +5611,11 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 - - + + + - - +
{{_('Edit')}}
{{_('Delete User')}}

{{_('Delete User')}}
TestBackupMetadata2120100 + Detail +
+
TestBackupMetadata - test_backup_all
+
PASS
+
TestBackupMetadata - test_backup_change_book_author
+
PASS
+
TestBackupMetadata - test_backup_change_book_description
+
PASS
+
TestBackupMetadata - test_backup_change_book_identifier
+
PASS
+
TestBackupMetadata - test_backup_change_book_language
+
PASS
+
TestBackupMetadata - test_backup_change_book_publisher
+
PASS
+
TestBackupMetadata - test_backup_change_book_publishing_date
+
PASS
+
TestBackupMetadata - test_backup_change_book_rating
+
PASS
+
TestBackupMetadata - test_backup_change_book_series_index
+
+
+ FAIL +
+ + + +
+
TestBackupMetadata - test_backup_change_book_tags
+
PASS
+
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_upload_book
+
PASS
TestBackupMetadataGdrive10010 + Detail +
+
TestBackupMetadataGdrive - test_backup_gdrive
+
+
+ ERROR +
+ + + +
_ErrorHolder10010 + Detail +
+
tearDownClass (test_backup_metadata_gdrive)
+
+
+ ERROR +
+ + + +
TestCli10101313 0 0 0 - Detail + Detail
TestCli - test_already_started
TestCli - test_bind_to_single_interface
TestCli - test_change_password
TestCli - test_cli_SSL_files
TestCli - test_cli_different_folder
TestCli - test_cli_different_settings_database
TestCli - test_dryrun_update
+
TestCli - test_enable_reconnect
+
PASS
TestCli - test_environ_port_setting
+
TestCli - test_logfile
+
PASS
TestCli - test_no_database
TestCli - test_settingsdb_not_writeable
+
TestCli - test_writeonly_static_files
+
PASS
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
TestEbookConvertCalibreGDrive7 6160 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
-
TestEbookConvertCalibreGDrive - test_thumbnail_cache
-
-
- FAIL -
- - - -
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
+
PASS
+
TestEditAdditionalBooks - test_edit_book_identifier_capital
+
PASS
+
TestEditAdditionalBooks - test_edit_book_identifier_standard
+
PASS
-
TestEditAdditionalBooks - test_edit_book_identifier
+
TestEditAdditionalBooks - test_edit_special_book_identifier
PASS
-
TestEditAdditionalBooks - test_edit_book_identifier_capital
+
TestEditAdditionalBooks - test_title_sort
PASS
-
TestEditAdditionalBooks - test_edit_book_identifier_standard
+
TestEditAdditionalBooks - test_upload_cbz_coverformats
PASS
-
TestEditAdditionalBooks - test_edit_special_book_identifier
+
TestEditAdditionalBooks - test_upload_edit_role
PASS
-
TestEditAdditionalBooks - test_title_sort
+
TestEditAdditionalBooks - test_upload_metadata_cb7
PASS
-
TestEditAdditionalBooks - test_upload_cbz_coverformats
+
TestEditAdditionalBooks - test_upload_metadata_cbr
PASS
-
TestEditAdditionalBooks - test_upload_edit_role
+
TestEditAdditionalBooks - test_upload_metadata_cbt
PASS
-
TestEditAdditionalBooks - test_upload_metadata_cbr
+
TestEditAdditionalBooks - test_writeonly_calibre_database
+
+
+ SKIP +
+ + +
PASS
-
TestEditAdditionalBooks - test_upload_metadata_cbt
+
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 11 0 01 0 - Detail + Detail
TestLoadMetadata - test_load_metadata
PASS +
+ ERROR +
+ + + +
0 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
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
TestSSL77000 - Detail -
TestSSL77000 + Detail +
+
TestSSL - test_SSL_None_setup_error
+
PASS
+
TestSSL - test_SSL_STARTTLS_setup_error
+
PASS
+
TestSSL - test_SSL_logging_email
+
PASS
+
TestSSL - test_SSL_non_admin_user
+
PASS
+
TestSSL - test_SSL_only
+
PASS
+
TestSSL - test_email_limit
+
PASS
+
TestSSL - test_filepicker_two_file
+
PASS
TestEmbedMetadata55000 + Detail +
+
TestEmbedMetadata - test_convert_file_embed_metadata
+
PASS
+
TestEmbedMetadata - test_convert_kepub_embed_metadata
+
PASS
-
TestSSL - test_SSL_None_setup_error
+
TestEmbedMetadata - test_download_check_metadata
PASS
-
TestSSL - test_SSL_STARTTLS_setup_error
+
TestEmbedMetadata - test_download_kepub_embed_metadata
PASS
-
TestSSL - test_SSL_logging_email
+
TestEmbedMetadata - test_download_permissions_missing_file
PASS
TestEmbedMetadataGdrive44000 + Detail +
-
TestSSL - test_SSL_non_admin_user
+
TestEmbedMetadataGdrive - test_convert_file_embed_metadata
PASS
-
TestSSL - test_SSL_only
+
TestEmbedMetadataGdrive - test_convert_kepub_embed_metadata
PASS
-
TestSSL - test_email_limit
+
TestEmbedMetadataGdrive - test_download_check_metadata
PASS
-
TestSSL - test_filepicker_two_file
+
TestEmbedMetadataGdrive - test_download_kepub_embed_metadata
PASS
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_sync_selected_shelfs
+
TestKoboSync - test_kobo_limit
+
PASS
+
TestKoboSync - test_kobo_no_download
PASS
-
TestKoboSync - test_kobo_upload_book
+
TestKoboSync - test_kobo_sync_selected_shelfs
PASS
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
TestLogin1515019181 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_log_hack
+
PASS
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_multi_user
+
+
+ FAIL +
+ + + +
+
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
TestReader55087 0 01 - Detail + Detail
+
TestReader - test_cb7_reader
+
SKIP
+
TestReader - test_comic_MACOS_files
+
PASS
TestReader - test_comic_reader
TestReader - test_epub_reader
TestReader - test_pdf_reader
-
TestReader - test_sound_listener
+
TestReader - test_single_file_comic
PASS
-
TestReader - test_txt_reader
+
TestReader - test_sound_listener
PASS
TestReadOnlyDatabase11000 - Detail -
-
TestReadOnlyDatabase - test_readonly_path
+
TestReader - test_txt_reader
PASS
TestReconnectTestReadOnlyDatabase 1 1 0 0 0 - Detail + Detail
-
TestReconnect - test_reconnect_endpoint
+
TestReadOnlyDatabase - test_readonly_path
PASS
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
TestSocket11000 + Detail +
+
TestSocket - test_socket_communication
+
PASS
TestSystemdActivation11000 + Detail +
+
TestSystemdActivation - test_systemd_activation
+
PASS
TestThumbnailsEnv 1 0 0 - Detail + Detail
TestThumbnailsEnv - test_cover_cache_env_on_database_change
TestThumbnails 85270 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
-
- FAIL -
- - - -
PASS
TestThumbnails - test_cover_for_series
TestThumbnails - test_cover_on_upload_book
TestThumbnails - test_remove_cover_from_cache
TestThumbnails - test_sideloaded_book
-
- FAIL -
- - - -
PASS
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
TestUploadEPubs4466 0 0 0 - Detail + Detail
+
TestUploadEPubs - test_upload_epub_comments
+
PASS
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
Total4234134784632 30710  
@@ -4837,13 +5643,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 Platform - Linux 5.13.0-40-generic #45~20.04.1-Ubuntu SMP Mon Apr 4 09:38:31 UTC 2022 x86_64 x86_64 + Linux 6.5.0-14-generic #14~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Nov 20 18:15:30 UTC 2 x86_64 x86_64 Basic Python - 3.8.10 + 3.10.12 Basic @@ -4855,43 +5661,43 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 APScheduler - 3.9.1 + 3.10.4 Basic Babel - 2.10.1 + 2.14.0 Basic - backports-abc - 0.5 + chardet + 4.0.0 Basic - chardet - 4.0.0 + Flask + 2.3.3 Basic - Flask - 2.0.3 + flask-babel + 4.0.0 Basic - Flask-Babel - 2.0.0 + Flask-Limiter + 3.5.0 Basic Flask-Login - 0.6.0 + 0.6.2 Basic @@ -4903,13 +5709,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 Flask-WTF - 1.0.1 + 1.2.1 Basic greenlet - 1.1.2 + 3.0.3 Basic @@ -4921,79 +5727,79 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 Jinja2 - 3.1.2 + 3.1.3 Basic lxml - 4.8.0 + 4.9.4 Basic pyasn1 - 0.4.8 + 0.5.1 Basic - PyPDF3 - 1.0.6 + pypdf + 3.15.5 Basic pytz - 2022.1 + 2023.3.post1 Basic requests - 2.27.1 + 2.31.0 Basic SQLAlchemy - 1.4.36 + 2.0.25 Basic tornado - 6.1 + 6.3.3 Basic Unidecode - 1.3.4 + 1.3.8 Basic Wand - 0.6.7 + 0.6.13 Basic Werkzeug - 2.0.3 + 2.3.8 Basic google-api-python-client - 2.46.0 + 2.114.0 TestCliGdrivedb httplib2 - 0.20.4 + 0.22.0 TestCliGdrivedb @@ -5005,25 +5811,25 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestCliGdrivedb PyYAML - 6.0 + 6.0.1 TestCliGdrivedb google-api-python-client - 2.46.0 + 2.114.0 TestEbookConvertCalibreGDrive httplib2 - 0.20.4 + 0.22.0 TestEbookConvertCalibreGDrive @@ -5035,25 +5841,25 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestEbookConvertCalibreGDrive PyYAML - 6.0 + 6.0.1 TestEbookConvertCalibreGDrive google-api-python-client - 2.46.0 + 2.114.0 TestEbookConvertGDriveKepubify httplib2 - 0.20.4 + 0.22.0 TestEbookConvertGDriveKepubify @@ -5065,37 +5871,49 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestEbookConvertGDriveKepubify PyYAML - 6.0 + 6.0.1 TestEbookConvertGDriveKepubify comicapi - 2.2.1 + 3.2.0 + TestEditAdditionalBooks + + + + py7zr + 0.20.8 TestEditAdditionalBooks rarfile - 4.0 + 4.1 TestEditAdditionalBooks + + py7zr + 0.20.8 + TestEditBooks + + google-api-python-client - 2.46.0 + 2.114.0 TestEditAuthorsGdrive httplib2 - 0.20.4 + 0.22.0 TestEditAuthorsGdrive @@ -5107,31 +5925,31 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestEditAuthorsGdrive PyYAML - 6.0 + 6.0.1 TestEditAuthorsGdrive beautifulsoup4 - 4.11.1 + 4.12.3 TestLoadMetadata google-api-python-client - 2.46.0 + 2.114.0 TestEditBooksOnGdrive httplib2 - 0.20.4 + 0.22.0 TestEditBooksOnGdrive @@ -5143,37 +5961,67 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestEditBooksOnGdrive PyYAML - 6.0 + 6.0.1 TestEditBooksOnGdrive beautifulsoup4 - 4.11.1 + 4.12.3 TestLoadMetadataScholar scholarly - 1.6.0 + 1.7.11 TestLoadMetadataScholar google-api-python-client - 2.46.0 + 2.114.0 + TestEmbedMetadataGdrive + + + + httplib2 + 0.22.0 + TestEmbedMetadataGdrive + + + + oauth2client + 4.1.3 + TestEmbedMetadataGdrive + + + + PyDrive2 + 1.19.0 + TestEmbedMetadataGdrive + + + + PyYAML + 6.0.1 + TestEmbedMetadataGdrive + + + + google-api-python-client + 2.114.0 TestSetupGdrive httplib2 - 0.20.4 + 0.22.0 TestSetupGdrive @@ -5185,13 +6033,13 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 PyDrive2 - 1.10.1 + 1.19.0 TestSetupGdrive PyYAML - 6.0 + 6.0.1 TestSetupGdrive @@ -5203,19 +6051,19 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 python-Levenshtein - 0.12.2 + 0.23.0 TestGoodreads jsonschema - 4.4.0 + 4.21.0 TestKoboSync jsonschema - 4.4.0 + 4.21.0 TestKoboSyncBig @@ -5227,25 +6075,25 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04 jsonschema - 4.4.0 + 4.21.0 TestLdapLogin python-ldap - 3.4.0 + 3.4.4 TestLdapLogin Flask-Dance - 6.0.0 + 7.0.1 TestOAuthLogin SQLAlchemy-Utils - 0.38.2 + 0.41.1 TestOAuthLogin @@ -5257,7 +6105,7 @@ AssertionError: 0.03724830839072722 not greater than or equal to 0.04