mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-18 14:10:30 +00:00
Merge branch 'master' into add_lubimyczytac.pl_meta_provider
This commit is contained in:
commit
20b5a9a2c0
@ -19,7 +19,7 @@ Calibre-Web is a web app providing a clean interface for browsing, reading and d
|
|||||||
- full graphical setup
|
- full graphical setup
|
||||||
- User management with fine-grained per-user permissions
|
- User management with fine-grained per-user permissions
|
||||||
- Admin interface
|
- Admin interface
|
||||||
- User Interface in brazilian, czech, dutch, english, finnish, french, german, greek, hungarian, italian, japanese, khmer, polish, russian, simplified and traditional chinese, spanish, swedish, turkish, ukrainian
|
- 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
|
- OPDS feed for eBook reader apps
|
||||||
- Filter and search by titles, authors, tags, series and language
|
- Filter and search by titles, authors, tags, series and language
|
||||||
- Create a custom book collection (shelves)
|
- Create a custom book collection (shelves)
|
||||||
|
@ -27,3 +27,6 @@ To receive fixes for security vulnerabilities it is required to always upgrade t
|
|||||||
| V 0.6.14|Cross-Site Scripting vulnerability on typeahead inputs. Thanks to @notdodo||
|
| V 0.6.14|Cross-Site Scripting vulnerability on typeahead inputs. Thanks to @notdodo||
|
||||||
|
|
||||||
|
|
||||||
|
## Staement regarding Log4j (CVE-2021-44228 and related)
|
||||||
|
|
||||||
|
Calibre-web is not affected by bugs related to Log4j. Calibre-Web is a python program, therefore not using Java, and not using the Java logging feature log4j.
|
||||||
|
19
cps/about.py
19
cps/about.py
@ -74,13 +74,22 @@ opt = dep_check.load_dependencys(True)
|
|||||||
for i in (req + opt):
|
for i in (req + opt):
|
||||||
ret[i[1]] = i[0]
|
ret[i[1]] = i[0]
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
if not ret:
|
if not ret:
|
||||||
_VERSIONS = OrderedDict(
|
_VERSIONS = OrderedDict(
|
||||||
Platform = '{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()),
|
Platform = '{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()),
|
||||||
Python=sys.version,
|
Python=sys.version,
|
||||||
Calibre_Web=constants.STABLE_VERSION['version'] + ' - '
|
Calibre_Web=calibre_web_version,
|
||||||
+ constants.NIGHTLY_VERSION[0].replace('%','%%') + ' - '
|
|
||||||
+ constants.NIGHTLY_VERSION[1].replace('%','%%'),
|
|
||||||
WebServer=server.VERSION,
|
WebServer=server.VERSION,
|
||||||
Flask=flask.__version__,
|
Flask=flask.__version__,
|
||||||
Flask_Login=flask_loginVersion,
|
Flask_Login=flask_loginVersion,
|
||||||
@ -110,9 +119,7 @@ else:
|
|||||||
_VERSIONS = OrderedDict(
|
_VERSIONS = OrderedDict(
|
||||||
Platform = '{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()),
|
Platform = '{0[0]} {0[2]} {0[3]} {0[4]} {0[5]}'.format(platform.uname()),
|
||||||
Python = sys.version,
|
Python = sys.version,
|
||||||
Calibre_Web = constants.STABLE_VERSION['version'] + ' - '
|
Calibre_Web=calibre_web_version,
|
||||||
+ constants.NIGHTLY_VERSION[0].replace('%', '%%') + ' - '
|
|
||||||
+ constants.NIGHTLY_VERSION[1].replace('%', '%%'),
|
|
||||||
Werkzeug = werkzeug.__version__,
|
Werkzeug = werkzeug.__version__,
|
||||||
Jinja2=jinja2.__version__,
|
Jinja2=jinja2.__version__,
|
||||||
pySqlite = sqlite3.version,
|
pySqlite = sqlite3.version,
|
||||||
|
34
cps/admin.py
34
cps/admin.py
@ -129,11 +129,11 @@ def admin_forbidden():
|
|||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/shutdown")
|
@admi.route("/shutdown", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def shutdown():
|
def shutdown():
|
||||||
task = int(request.args.get("parameter").strip())
|
task = request.get_json().get('parameter', -1)
|
||||||
showtext = {}
|
showtext = {}
|
||||||
if task in (0, 1): # valid commandos received
|
if task in (0, 1): # valid commandos received
|
||||||
# close all database connections
|
# close all database connections
|
||||||
@ -756,7 +756,12 @@ def prepare_tags(user, action, tags_name, id_list):
|
|||||||
return ",".join(saved_tags_list)
|
return ",".join(saved_tags_list)
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/ajax/addrestriction/<int:res_type>", defaults={"user_id": 0}, methods=['POST'])
|
@admi.route("/ajax/addrestriction/<int:res_type>", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@admin_required
|
||||||
|
def add_user_0_restriction(res_type):
|
||||||
|
return add_restriction(res_type, 0)
|
||||||
|
|
||||||
@admi.route("/ajax/addrestriction/<int:res_type>/<int:user_id>", methods=['POST'])
|
@admi.route("/ajax/addrestriction/<int:res_type>/<int:user_id>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
@ -803,7 +808,13 @@ def add_restriction(res_type, user_id):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/ajax/deleterestriction/<int:res_type>", defaults={"user_id": 0}, methods=['POST'])
|
@admi.route("/ajax/deleterestriction/<int:res_type>", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@admin_required
|
||||||
|
def delete_user_0_restriction(res_type):
|
||||||
|
return delete_restriction(res_type, 0)
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/ajax/deleterestriction/<int:res_type>/<int:user_id>", methods=['POST'])
|
@admi.route("/ajax/deleterestriction/<int:res_type>/<int:user_id>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
@ -895,7 +906,7 @@ def list_restriction(res_type, user_id):
|
|||||||
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@admi.route("/ajax/fullsync")
|
@admi.route("/ajax/fullsync", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def ajax_fullsync():
|
def ajax_fullsync():
|
||||||
count = ub.session.query(ub.KoboSyncedBooks).filter(current_user.id == ub.KoboSyncedBooks.user_id).delete()
|
count = ub.session.query(ub.KoboSyncedBooks).filter(current_user.id == ub.KoboSyncedBooks.user_id).delete()
|
||||||
@ -1404,7 +1415,16 @@ def _delete_user(content):
|
|||||||
for us in ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id):
|
for us in ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id):
|
||||||
ub.session.query(ub.BookShelf).filter(us.id == ub.BookShelf.shelf).delete()
|
ub.session.query(ub.BookShelf).filter(us.id == ub.BookShelf.shelf).delete()
|
||||||
ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id).delete()
|
ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id).delete()
|
||||||
|
ub.session.query(ub.Bookmark).filter(content.id == ub.Bookmark.user_id).delete()
|
||||||
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
|
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
|
||||||
|
ub.session.query(ub.ArchivedBook).filter(ub.ArchivedBook.user_id == content.id).delete()
|
||||||
|
ub.session.query(ub.RemoteAuthToken).filter(ub.RemoteAuthToken.user_id == content.id).delete()
|
||||||
|
ub.session.query(ub.User_Sessions).filter(ub.User_Sessions.user_id == content.id).delete()
|
||||||
|
ub.session.query(ub.KoboSyncedBooks).filter(ub.KoboSyncedBooks.user_id == content.id).delete()
|
||||||
|
# delete KoboReadingState and all it's children
|
||||||
|
kobo_entries = ub.session.query(ub.KoboReadingState).filter(ub.KoboReadingState.user_id == content.id).all()
|
||||||
|
for kobo_entry in kobo_entries:
|
||||||
|
ub.session.delete(kobo_entry)
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
log.info(u"User {} deleted".format(content.name))
|
log.info(u"User {} deleted".format(content.name))
|
||||||
return(_(u"User '%(nick)s' deleted", nick=content.name))
|
return(_(u"User '%(nick)s' deleted", nick=content.name))
|
||||||
@ -1615,7 +1635,7 @@ def edit_user(user_id):
|
|||||||
page="edituser")
|
page="edituser")
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/admin/resetpassword/<int:user_id>")
|
@admi.route("/admin/resetpassword/<int:user_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def reset_user_password(user_id):
|
def reset_user_password(user_id):
|
||||||
@ -1791,7 +1811,7 @@ def ldap_import_create_user(user, user_data):
|
|||||||
return 0, message
|
return 0, message
|
||||||
|
|
||||||
|
|
||||||
@admi.route('/import_ldap_users')
|
@admi.route('/import_ldap_users', methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def import_ldap_users():
|
def import_ldap_users():
|
||||||
|
@ -23,6 +23,7 @@ import re
|
|||||||
import ast
|
import ast
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy import Table, Column, ForeignKey, CheckConstraint
|
from sqlalchemy import Table, Column, ForeignKey, CheckConstraint
|
||||||
@ -166,6 +167,8 @@ class Identifiers(Base):
|
|||||||
return u"https://portal.issn.org/resource/ISSN/{0}".format(self.val)
|
return u"https://portal.issn.org/resource/ISSN/{0}".format(self.val)
|
||||||
elif format_type == "isfdb":
|
elif format_type == "isfdb":
|
||||||
return u"http://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val)
|
return u"http://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val)
|
||||||
|
elif self.val.lower().startswith("javascript:"):
|
||||||
|
return quote(self.val)
|
||||||
else:
|
else:
|
||||||
return u"{0}".format(self.val)
|
return u"{0}".format(self.val)
|
||||||
|
|
||||||
@ -796,8 +799,8 @@ class CalibreDB():
|
|||||||
def speaking_language(self, languages=None, return_all_languages=False, with_count=False, reverse_order=False):
|
def speaking_language(self, languages=None, return_all_languages=False, with_count=False, reverse_order=False):
|
||||||
from . import get_locale
|
from . import get_locale
|
||||||
|
|
||||||
if not languages:
|
|
||||||
if with_count:
|
if with_count:
|
||||||
|
if not languages:
|
||||||
languages = self.session.query(Languages, func.count('books_languages_link.book'))\
|
languages = self.session.query(Languages, func.count('books_languages_link.book'))\
|
||||||
.join(books_languages_link).join(Books)\
|
.join(books_languages_link).join(Books)\
|
||||||
.filter(self.common_filters(return_all_languages=return_all_languages)) \
|
.filter(self.common_filters(return_all_languages=return_all_languages)) \
|
||||||
@ -806,6 +809,7 @@ class CalibreDB():
|
|||||||
lang[0].name = isoLanguages.get_language_name(get_locale(), lang[0].lang_code)
|
lang[0].name = isoLanguages.get_language_name(get_locale(), lang[0].lang_code)
|
||||||
return sorted(languages, key=lambda x: x[0].name, reverse=reverse_order)
|
return sorted(languages, key=lambda x: x[0].name, reverse=reverse_order)
|
||||||
else:
|
else:
|
||||||
|
if not languages:
|
||||||
languages = self.session.query(Languages) \
|
languages = self.session.query(Languages) \
|
||||||
.join(books_languages_link) \
|
.join(books_languages_link) \
|
||||||
.join(Books) \
|
.join(Books) \
|
||||||
|
28
cps/editbooks.py
Normal file → Executable file
28
cps/editbooks.py
Normal file → Executable file
@ -26,6 +26,8 @@ import json
|
|||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from markupsafe import escape
|
from markupsafe import escape
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from lxml.html.clean import clean_html
|
from lxml.html.clean import clean_html
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -51,13 +53,6 @@ from .tasks.upload import TaskUpload
|
|||||||
from .render_template import render_title_template
|
from .render_template import render_title_template
|
||||||
from .usermanagement import login_required_if_no_ano
|
from .usermanagement import login_required_if_no_ano
|
||||||
|
|
||||||
try:
|
|
||||||
from functools import wraps
|
|
||||||
except ImportError:
|
|
||||||
pass # We're not using Python 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
editbook = Blueprint('editbook', __name__)
|
editbook = Blueprint('editbook', __name__)
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
@ -237,14 +232,14 @@ def modify_identifiers(input_identifiers, db_identifiers, db_session):
|
|||||||
changed = True
|
changed = True
|
||||||
return changed, error
|
return changed, error
|
||||||
|
|
||||||
@editbook.route("/ajax/delete/<int:book_id>")
|
@editbook.route("/ajax/delete/<int:book_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_book_from_details(book_id):
|
def delete_book_from_details(book_id):
|
||||||
return Response(delete_book_from_table(book_id, "", True), mimetype='application/json')
|
return Response(delete_book_from_table(book_id, "", True), mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
@editbook.route("/delete/<int:book_id>", defaults={'book_format': ""})
|
@editbook.route("/delete/<int:book_id>", defaults={'book_format': ""}, methods=["POST"])
|
||||||
@editbook.route("/delete/<int:book_id>/<string:book_format>")
|
@editbook.route("/delete/<int:book_id>/<string:book_format>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_book_ajax(book_id, book_format):
|
def delete_book_ajax(book_id, book_format):
|
||||||
return delete_book_from_table(book_id, book_format, False)
|
return delete_book_from_table(book_id, book_format, False)
|
||||||
@ -363,6 +358,15 @@ def delete_book_from_table(book_id, book_format, jsonResponse):
|
|||||||
# book not found
|
# book not found
|
||||||
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
||||||
return render_delete_book_result(book_format, jsonResponse, warning, book_id)
|
return render_delete_book_result(book_format, jsonResponse, warning, book_id)
|
||||||
|
message = _("You are missing permissions to delete books")
|
||||||
|
if jsonResponse:
|
||||||
|
return json.dumps({"location": url_for("editbook.edit_book", book_id=book_id),
|
||||||
|
"type": "danger",
|
||||||
|
"format": "",
|
||||||
|
"message": message})
|
||||||
|
else:
|
||||||
|
flash(message, category="error")
|
||||||
|
return redirect(url_for('editbook.edit_book', book_id=book_id))
|
||||||
|
|
||||||
|
|
||||||
def render_edit_book(book_id):
|
def render_edit_book(book_id):
|
||||||
@ -832,7 +836,7 @@ def edit_book(book_id):
|
|||||||
|
|
||||||
if modif_date:
|
if modif_date:
|
||||||
book.last_modified = datetime.utcnow()
|
book.last_modified = datetime.utcnow()
|
||||||
kobo_sync_status.remove_synced_book(edited_books_id)
|
kobo_sync_status.remove_synced_book(edited_books_id, all=True)
|
||||||
|
|
||||||
calibre_db.session.merge(book)
|
calibre_db.session.merge(book)
|
||||||
calibre_db.session.commit()
|
calibre_db.session.commit()
|
||||||
@ -1014,7 +1018,7 @@ def move_coverfile(meta, db_book):
|
|||||||
category="error")
|
category="error")
|
||||||
|
|
||||||
|
|
||||||
@editbook.route("/upload", methods=["GET", "POST"])
|
@editbook.route("/upload", methods=["POST"])
|
||||||
@login_required_if_no_ano
|
@login_required_if_no_ano
|
||||||
@upload_required
|
@upload_required
|
||||||
def upload():
|
def upload():
|
||||||
|
@ -109,7 +109,7 @@ def revoke_watch_gdrive():
|
|||||||
try:
|
try:
|
||||||
gdriveutils.stopChannel(gdriveutils.Gdrive.Instance().drive, last_watch_response['id'],
|
gdriveutils.stopChannel(gdriveutils.Gdrive.Instance().drive, last_watch_response['id'],
|
||||||
last_watch_response['resourceId'])
|
last_watch_response['resourceId'])
|
||||||
except HttpError:
|
except (HttpError, AttributeError):
|
||||||
pass
|
pass
|
||||||
config.config_google_drive_watch_changes_response = {}
|
config.config_google_drive_watch_changes_response = {}
|
||||||
config.save()
|
config.save()
|
||||||
|
@ -56,11 +56,13 @@ try:
|
|||||||
from pydrive2.auth import GoogleAuth
|
from pydrive2.auth import GoogleAuth
|
||||||
from pydrive2.drive import GoogleDrive
|
from pydrive2.drive import GoogleDrive
|
||||||
from pydrive2.auth import RefreshError
|
from pydrive2.auth import RefreshError
|
||||||
|
from pydrive2.files import ApiRequestError
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
try:
|
try:
|
||||||
from pydrive.auth import GoogleAuth
|
from pydrive.auth import GoogleAuth
|
||||||
from pydrive.drive import GoogleDrive
|
from pydrive.drive import GoogleDrive
|
||||||
from pydrive.auth import RefreshError
|
from pydrive.auth import RefreshError
|
||||||
|
from pydrive.files import ApiRequestError
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
importError = err
|
importError = err
|
||||||
gdrive_support = False
|
gdrive_support = False
|
||||||
@ -322,6 +324,11 @@ def getFolderId(path, drive):
|
|||||||
log.error("gdrive.db DB is not Writeable")
|
log.error("gdrive.db DB is not Writeable")
|
||||||
log.debug('Database error: %s', ex)
|
log.debug('Database error: %s', ex)
|
||||||
session.rollback()
|
session.rollback()
|
||||||
|
except ApiRequestError as ex:
|
||||||
|
log.error('{} {}'.format(ex.error['message'], path))
|
||||||
|
session.rollback()
|
||||||
|
except RefreshError as ex:
|
||||||
|
log.error(ex)
|
||||||
return currentFolderId
|
return currentFolderId
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,11 +38,8 @@ from sqlalchemy.sql.expression import true, false, and_, text, func
|
|||||||
from werkzeug.datastructures import Headers
|
from werkzeug.datastructures import Headers
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
from markupsafe import escape
|
from markupsafe import escape
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
try:
|
|
||||||
from urllib.parse import quote
|
|
||||||
except ImportError:
|
|
||||||
from urllib import quote
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import unidecode
|
import unidecode
|
||||||
@ -233,7 +230,7 @@ def get_valid_filename(value, replace_whitespace=True):
|
|||||||
value = value[:-1]+u'_'
|
value = value[:-1]+u'_'
|
||||||
value = value.replace("/", "_").replace(":", "_").strip('\0')
|
value = value.replace("/", "_").replace(":", "_").strip('\0')
|
||||||
if use_unidecode:
|
if use_unidecode:
|
||||||
if not config.config_unicode_filename:
|
if config.config_unicode_filename:
|
||||||
value = (unidecode.unidecode(value))
|
value = (unidecode.unidecode(value))
|
||||||
else:
|
else:
|
||||||
value = value.replace(u'§', u'SS')
|
value = value.replace(u'§', u'SS')
|
||||||
@ -673,9 +670,9 @@ def save_cover(img, book_path):
|
|||||||
|
|
||||||
def do_download_file(book, book_format, client, data, headers):
|
def do_download_file(book, book_format, client, data, headers):
|
||||||
if config.config_use_google_drive:
|
if config.config_use_google_drive:
|
||||||
startTime = time.time()
|
#startTime = time.time()
|
||||||
df = gd.getFileFromEbooksFolder(book.path, data.name + "." + book_format)
|
df = gd.getFileFromEbooksFolder(book.path, data.name + "." + book_format)
|
||||||
log.debug('%s', time.time() - startTime)
|
#log.debug('%s', time.time() - startTime)
|
||||||
if df:
|
if df:
|
||||||
return gd.do_gdrive_download(df, headers)
|
return gd.do_gdrive_download(df, headers)
|
||||||
else:
|
else:
|
||||||
|
@ -51,11 +51,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "běloruština",
|
"bel": "běloruština",
|
||||||
"bem": "bemba (Zambie)",
|
"bem": "bemba (Zambie)",
|
||||||
"ben": "bengálština",
|
"ben": "bengálština",
|
||||||
"berinomo": "bit",
|
|
||||||
"bho": "bhódžpurština",
|
"bho": "bhódžpurština",
|
||||||
"bik": "bikolština",
|
"bik": "bikolština",
|
||||||
"bin": "bini",
|
"bin": "bini",
|
||||||
"bis": "bislamština",
|
"bis": "bislamština",
|
||||||
|
"bit": "berinomo",
|
||||||
"bla": "siksika",
|
"bla": "siksika",
|
||||||
"bod": "tibetština",
|
"bod": "tibetština",
|
||||||
"bos": "bosenština",
|
"bos": "bosenština",
|
||||||
@ -102,6 +102,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "holandský znakový jazyk",
|
||||||
"dua": "dualština",
|
"dua": "dualština",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "djula",
|
"dyu": "djula",
|
||||||
@ -164,6 +165,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "hiligayonština",
|
"hil": "hiligayonština",
|
||||||
"hin": "hindština",
|
"hin": "hindština",
|
||||||
"hit": "chetitština",
|
"hit": "chetitština",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "hmongština",
|
"hmn": "hmongština",
|
||||||
"hmo": "hiri motu",
|
"hmo": "hiri motu",
|
||||||
"hrv": "chorvatština",
|
"hrv": "chorvatština",
|
||||||
@ -474,11 +476,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Weißrussisch",
|
"bel": "Weißrussisch",
|
||||||
"bem": "Bemba (Sambia)",
|
"bem": "Bemba (Sambia)",
|
||||||
"ben": "Bengalisch",
|
"ben": "Bengalisch",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Blackfoot",
|
"bla": "Blackfoot",
|
||||||
"bod": "Tibetisch",
|
"bod": "Tibetisch",
|
||||||
"bos": "Bosnisch",
|
"bos": "Bosnisch",
|
||||||
@ -525,6 +527,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (Makrosprache)",
|
"doi": "Dogri (Makrosprache)",
|
||||||
"dsb": "Sorbisch; Nieder",
|
"dsb": "Sorbisch; Nieder",
|
||||||
|
"dse": "Niederländische Zeichensprache",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Niederländisch; Mittel (ca. 1050-1350)",
|
"dum": "Niederländisch; Mittel (ca. 1050-1350)",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
@ -587,6 +590,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligaynon",
|
"hil": "Hiligaynon",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hethitisch",
|
"hit": "Hethitisch",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Miao-Sprachen",
|
"hmn": "Miao-Sprachen",
|
||||||
"hmo": "Hiri-Motu",
|
"hmo": "Hiri-Motu",
|
||||||
"hrv": "Kroatisch",
|
"hrv": "Kroatisch",
|
||||||
@ -896,12 +900,12 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Λευκωρωσικά",
|
"bel": "Λευκωρωσικά",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Μπενγκάλι",
|
"ben": "Μπενγκάλι",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"byn": "Bilin",
|
"byn": "Bilin",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
"berinomo": "Bit",
|
|
||||||
"zbl": "Blissymbols",
|
"zbl": "Blissymbols",
|
||||||
"bos": "Βοσνιακά",
|
"bos": "Βοσνιακά",
|
||||||
"bra": "Braj",
|
"bra": "Braj",
|
||||||
@ -943,6 +947,7 @@ LANGUAGE_NAMES = {
|
|||||||
"dgr": "Dogrib",
|
"dgr": "Dogrib",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"nld": "Ολλανδικά",
|
"nld": "Ολλανδικά",
|
||||||
|
"dse": "Ολλανδική νοηματική γλώσσα",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
"dzo": "Dzongkha",
|
"dzo": "Dzongkha",
|
||||||
"efi": "Efik",
|
"efi": "Efik",
|
||||||
@ -971,6 +976,7 @@ LANGUAGE_NAMES = {
|
|||||||
"lug": "Ganda",
|
"lug": "Ganda",
|
||||||
"gay": "Gayo",
|
"gay": "Gayo",
|
||||||
"gba": "Gbaya (Central African Republic)",
|
"gba": "Gbaya (Central African Republic)",
|
||||||
|
"hmj": "Ge",
|
||||||
"gez": "Geez",
|
"gez": "Geez",
|
||||||
"kat": "Γεωργιανά",
|
"kat": "Γεωργιανά",
|
||||||
"deu": "Γερμανικά",
|
"deu": "Γερμανικά",
|
||||||
@ -1275,11 +1281,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Bielorruso",
|
"bel": "Bielorruso",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengalí",
|
"ben": "Bengalí",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bopurí",
|
"bho": "Bopurí",
|
||||||
"bik": "Bicolano",
|
"bik": "Bicolano",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Siksiká",
|
"bla": "Siksiká",
|
||||||
"bod": "Tibetano",
|
"bod": "Tibetano",
|
||||||
"bos": "Bosnio",
|
"bos": "Bosnio",
|
||||||
@ -1326,6 +1332,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolengua)",
|
"doi": "Dogri (macrolengua)",
|
||||||
"dsb": "Bajo sorabo",
|
"dsb": "Bajo sorabo",
|
||||||
|
"dse": "Lengua de signos neerlandesa",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Neerlandés medio (ca. 1050-1350)",
|
"dum": "Neerlandés medio (ca. 1050-1350)",
|
||||||
"dyu": "Diula",
|
"dyu": "Diula",
|
||||||
@ -1388,6 +1395,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligainón",
|
"hil": "Hiligainón",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hitita",
|
"hit": "Hitita",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri motu",
|
"hmo": "Hiri motu",
|
||||||
"hrv": "Croata",
|
"hrv": "Croata",
|
||||||
@ -1698,11 +1706,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "valkovenäjä",
|
"bel": "valkovenäjä",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "bengali",
|
"ben": "bengali",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "bhojpuri",
|
"bho": "bhojpuri",
|
||||||
"bik": "bikol",
|
"bik": "bikol",
|
||||||
"bin": "bini",
|
"bin": "bini",
|
||||||
"bis": "bislama",
|
"bis": "bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "mustajalka (siksika)",
|
"bla": "mustajalka (siksika)",
|
||||||
"bod": "tiibetti",
|
"bod": "tiibetti",
|
||||||
"bos": "bosnia",
|
"bos": "bosnia",
|
||||||
@ -1749,6 +1757,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "alasorbi",
|
"dsb": "alasorbi",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "duala",
|
"dua": "duala",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "dyula",
|
"dyu": "dyula",
|
||||||
@ -1811,6 +1820,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "hiligaynon",
|
"hil": "hiligaynon",
|
||||||
"hin": "hindi",
|
"hin": "hindi",
|
||||||
"hit": "heetti",
|
"hit": "heetti",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "hmong",
|
"hmn": "hmong",
|
||||||
"hmo": "hiri-motu",
|
"hmo": "hiri-motu",
|
||||||
"hrv": "kroatia",
|
"hrv": "kroatia",
|
||||||
@ -2121,11 +2131,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "biélorusse",
|
"bel": "biélorusse",
|
||||||
"bem": "bemba (Zambie)",
|
"bem": "bemba (Zambie)",
|
||||||
"ben": "bengali",
|
"ben": "bengali",
|
||||||
"berinomo": "bit",
|
|
||||||
"bho": "bhojpuri",
|
"bho": "bhojpuri",
|
||||||
"bik": "bikol",
|
"bik": "bikol",
|
||||||
"bin": "bini",
|
"bin": "bini",
|
||||||
"bis": "bislama",
|
"bis": "bislama",
|
||||||
|
"bit": "berinomo",
|
||||||
"bla": "pied-noir",
|
"bla": "pied-noir",
|
||||||
"bod": "tibétain",
|
"bod": "tibétain",
|
||||||
"bos": "bosniaque",
|
"bos": "bosniaque",
|
||||||
@ -2172,6 +2182,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "dhivehi",
|
"div": "dhivehi",
|
||||||
"doi": "dogri (macrolangue)",
|
"doi": "dogri (macrolangue)",
|
||||||
"dsb": "bas-sorbien",
|
"dsb": "bas-sorbien",
|
||||||
|
"dse": "langue des signes néerlandaise",
|
||||||
"dua": "duala",
|
"dua": "duala",
|
||||||
"dum": "néerlandais moyen (environ 1050-1350)",
|
"dum": "néerlandais moyen (environ 1050-1350)",
|
||||||
"dyu": "dioula",
|
"dyu": "dioula",
|
||||||
@ -2234,6 +2245,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "hiligaynon",
|
"hil": "hiligaynon",
|
||||||
"hin": "hindi",
|
"hin": "hindi",
|
||||||
"hit": "hittite",
|
"hit": "hittite",
|
||||||
|
"hmj": "ge",
|
||||||
"hmn": "hmong",
|
"hmn": "hmong",
|
||||||
"hmo": "hiri Motu",
|
"hmo": "hiri Motu",
|
||||||
"hrv": "croate",
|
"hrv": "croate",
|
||||||
@ -2544,11 +2556,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "belarusz",
|
"bel": "belarusz",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "bengáli",
|
"ben": "bengáli",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "bhodzspuri",
|
"bho": "bhodzspuri",
|
||||||
"bik": "bikol",
|
"bik": "bikol",
|
||||||
"bin": "bini",
|
"bin": "bini",
|
||||||
"bis": "biszlama",
|
"bis": "biszlama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "szikszika",
|
"bla": "szikszika",
|
||||||
"bod": "tibeti",
|
"bod": "tibeti",
|
||||||
"bos": "bosnyák",
|
"bos": "bosnyák",
|
||||||
@ -2595,6 +2607,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "duala",
|
"dua": "duala",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "djula",
|
"dyu": "djula",
|
||||||
@ -2657,6 +2670,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "hiligajnon",
|
"hil": "hiligajnon",
|
||||||
"hin": "hindi",
|
"hin": "hindi",
|
||||||
"hit": "hettita",
|
"hit": "hettita",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "hmong",
|
"hmn": "hmong",
|
||||||
"hmo": "hiri motu",
|
"hmo": "hiri motu",
|
||||||
"hrv": "horvát",
|
"hrv": "horvát",
|
||||||
@ -2967,11 +2981,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Bielorusso",
|
"bel": "Bielorusso",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengalese",
|
"ben": "Bengalese",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "bicol",
|
"bik": "bicol",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "bislama",
|
"bis": "bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Siksika",
|
"bla": "Siksika",
|
||||||
"bod": "Tibetano",
|
"bod": "Tibetano",
|
||||||
"bos": "Bosniaco",
|
"bos": "Bosniaco",
|
||||||
@ -3018,6 +3032,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolingua)",
|
"doi": "Dogri (macrolingua)",
|
||||||
"dsb": "Lusaziano inferiore",
|
"dsb": "Lusaziano inferiore",
|
||||||
|
"dse": "Olandense (linguaggio dei segni)",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Olandese medio (ca. 1050-1350)",
|
"dum": "Olandese medio (ca. 1050-1350)",
|
||||||
"dyu": "Diula",
|
"dyu": "Diula",
|
||||||
@ -3080,6 +3095,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligayna",
|
"hil": "Hiligayna",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "hittite",
|
"hit": "hittite",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri motu",
|
"hmo": "Hiri motu",
|
||||||
"hrv": "Croato",
|
"hrv": "Croato",
|
||||||
@ -3390,11 +3406,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "白ロシア語",
|
"bel": "白ロシア語",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "ベンガル語",
|
"ben": "ベンガル語",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "ボージプリー語",
|
"bho": "ボージプリー語",
|
||||||
"bik": "ビコル語",
|
"bik": "ビコル語",
|
||||||
"bin": "ビニ語",
|
"bin": "ビニ語",
|
||||||
"bis": "ビスラマ語",
|
"bis": "ビスラマ語",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "ブラックフット語",
|
"bla": "ブラックフット語",
|
||||||
"bod": "チベット語",
|
"bod": "チベット語",
|
||||||
"bos": "ボスニア語",
|
"bos": "ボスニア語",
|
||||||
@ -3441,6 +3457,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "ドゥアラ語",
|
"dua": "ドゥアラ語",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "デュラ語",
|
"dyu": "デュラ語",
|
||||||
@ -3503,6 +3520,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "ヒリジャノン語",
|
"hil": "ヒリジャノン語",
|
||||||
"hin": "ヒンディー語",
|
"hin": "ヒンディー語",
|
||||||
"hit": "ヒッタイト語",
|
"hit": "ヒッタイト語",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "フモング語",
|
"hmn": "フモング語",
|
||||||
"hmo": "ヒリモトゥ語",
|
"hmo": "ヒリモトゥ語",
|
||||||
"hrv": "クロアチア語",
|
"hrv": "クロアチア語",
|
||||||
@ -3813,11 +3831,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Belarusian",
|
"bel": "Belarusian",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengali",
|
"ben": "Bengali",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Siksika",
|
"bla": "Siksika",
|
||||||
"bod": "Tibetan",
|
"bod": "Tibetan",
|
||||||
"bos": "Bosnian",
|
"bos": "Bosnian",
|
||||||
@ -3864,6 +3882,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
@ -3926,6 +3945,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligaynon",
|
"hil": "Hiligaynon",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hittite",
|
"hit": "Hittite",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri Motu",
|
"hmo": "Hiri Motu",
|
||||||
"hrv": "Croatian",
|
"hrv": "Croatian",
|
||||||
@ -4197,6 +4217,384 @@ LANGUAGE_NAMES = {
|
|||||||
"zxx": "No linguistic content",
|
"zxx": "No linguistic content",
|
||||||
"zza": "Zaza"
|
"zza": "Zaza"
|
||||||
},
|
},
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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": {
|
"nl": {
|
||||||
"aar": "Afar; Hamitisch",
|
"aar": "Afar; Hamitisch",
|
||||||
"abk": "Abchazisch",
|
"abk": "Abchazisch",
|
||||||
@ -4236,11 +4634,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Wit-Russisch; Belarussisch",
|
"bel": "Wit-Russisch; Belarussisch",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengaals",
|
"ben": "Bengaals",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"bin": "Bini; Edo",
|
"bin": "Bini; Edo",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Siksika",
|
"bla": "Siksika",
|
||||||
"bod": "Tibetaans",
|
"bod": "Tibetaans",
|
||||||
"bos": "Bosnisch",
|
"bos": "Bosnisch",
|
||||||
@ -4287,6 +4685,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Divehi",
|
"div": "Divehi",
|
||||||
"doi": "Dogri",
|
"doi": "Dogri",
|
||||||
"dsb": "Sorbisch; lager",
|
"dsb": "Sorbisch; lager",
|
||||||
|
"dse": "Nederlandse gebarentaal",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Nederlands; middel (ca. 1050-1350)",
|
"dum": "Nederlands; middel (ca. 1050-1350)",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
@ -4349,6 +4748,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligainoons",
|
"hil": "Hiligainoons",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hittitisch",
|
"hit": "Hittitisch",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri Motu",
|
"hmo": "Hiri Motu",
|
||||||
"hrv": "Kroatisch",
|
"hrv": "Kroatisch",
|
||||||
@ -4659,11 +5059,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "białoruski",
|
"bel": "białoruski",
|
||||||
"bem": "bemba (Zambia)",
|
"bem": "bemba (Zambia)",
|
||||||
"ben": "bengalski",
|
"ben": "bengalski",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "bhodźpuri",
|
"bho": "bhodźpuri",
|
||||||
"bik": "bikol",
|
"bik": "bikol",
|
||||||
"bin": "edo",
|
"bin": "edo",
|
||||||
"bis": "bislama",
|
"bis": "bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "siksika",
|
"bla": "siksika",
|
||||||
"bod": "tybetański",
|
"bod": "tybetański",
|
||||||
"bos": "bośniacki",
|
"bos": "bośniacki",
|
||||||
@ -4710,6 +5110,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "malediwski; divehi",
|
"div": "malediwski; divehi",
|
||||||
"doi": "dogri (makrojęzyk)",
|
"doi": "dogri (makrojęzyk)",
|
||||||
"dsb": "dolnołużycki",
|
"dsb": "dolnołużycki",
|
||||||
|
"dse": "holenderski język migowy",
|
||||||
"dua": "duala",
|
"dua": "duala",
|
||||||
"dum": "holenderski średniowieczny (ok. 1050-1350)",
|
"dum": "holenderski średniowieczny (ok. 1050-1350)",
|
||||||
"dyu": "diula",
|
"dyu": "diula",
|
||||||
@ -4772,6 +5173,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "hiligajnon",
|
"hil": "hiligajnon",
|
||||||
"hin": "hindi",
|
"hin": "hindi",
|
||||||
"hit": "hetycki",
|
"hit": "hetycki",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "hmong",
|
"hmn": "hmong",
|
||||||
"hmo": "hiri motu",
|
"hmo": "hiri motu",
|
||||||
"hrv": "chorwacki",
|
"hrv": "chorwacki",
|
||||||
@ -5081,12 +5483,12 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Belarusian",
|
"bel": "Belarusian",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengali",
|
"ben": "Bengali",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"byn": "Bilin",
|
"byn": "Bilin",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
"berinomo": "Bit",
|
|
||||||
"zbl": "Blissymbols",
|
"zbl": "Blissymbols",
|
||||||
"bos": "Bosnian",
|
"bos": "Bosnian",
|
||||||
"bra": "Braj",
|
"bra": "Braj",
|
||||||
@ -5128,6 +5530,7 @@ LANGUAGE_NAMES = {
|
|||||||
"dgr": "Dogrib",
|
"dgr": "Dogrib",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"nld": "Holandês",
|
"nld": "Holandês",
|
||||||
|
"dse": "Língua gestual holandesa",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
"dzo": "Dzongkha",
|
"dzo": "Dzongkha",
|
||||||
"efi": "Efik",
|
"efi": "Efik",
|
||||||
@ -5156,6 +5559,7 @@ LANGUAGE_NAMES = {
|
|||||||
"lug": "Ganda",
|
"lug": "Ganda",
|
||||||
"gay": "Gayo",
|
"gay": "Gayo",
|
||||||
"gba": "Gbaya (Central African Republic)",
|
"gba": "Gbaya (Central African Republic)",
|
||||||
|
"hmj": "Ge",
|
||||||
"gez": "Geez",
|
"gez": "Geez",
|
||||||
"kat": "Georgiano",
|
"kat": "Georgiano",
|
||||||
"deu": "Alemão",
|
"deu": "Alemão",
|
||||||
@ -5458,11 +5862,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Белорусский",
|
"bel": "Белорусский",
|
||||||
"bem": "Бемба (Замбия)",
|
"bem": "Бемба (Замбия)",
|
||||||
"ben": "Бенгальский",
|
"ben": "Бенгальский",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Бходжпури",
|
"bho": "Бходжпури",
|
||||||
"bik": "Бикольский",
|
"bik": "Бикольский",
|
||||||
"bin": "Бини",
|
"bin": "Бини",
|
||||||
"bis": "Бислама",
|
"bis": "Бислама",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Сиксика",
|
"bla": "Сиксика",
|
||||||
"bod": "Тибетский",
|
"bod": "Тибетский",
|
||||||
"bos": "Боснийский",
|
"bos": "Боснийский",
|
||||||
@ -5509,6 +5913,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "Дуала",
|
"dua": "Дуала",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "Диула (Дьюла)",
|
"dyu": "Диула (Дьюла)",
|
||||||
@ -5571,6 +5976,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Хилигайнон",
|
"hil": "Хилигайнон",
|
||||||
"hin": "Хинди",
|
"hin": "Хинди",
|
||||||
"hit": "Хиттит",
|
"hit": "Хиттит",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Хмонг",
|
"hmn": "Хмонг",
|
||||||
"hmo": "Хири Моту",
|
"hmo": "Хири Моту",
|
||||||
"hrv": "Хорватский",
|
"hrv": "Хорватский",
|
||||||
@ -5881,11 +6287,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Vitryska",
|
"bel": "Vitryska",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengaliska",
|
"ben": "Bengaliska",
|
||||||
"berinomo": "Bit",
|
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"bin": "Edo (bini)",
|
"bin": "Edo (bini)",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "Siksika (svartfotindianernas språk)",
|
"bla": "Siksika (svartfotindianernas språk)",
|
||||||
"bod": "Tibetanska",
|
"bod": "Tibetanska",
|
||||||
"bos": "Bosniska",
|
"bos": "Bosniska",
|
||||||
@ -5932,6 +6338,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Divehi",
|
"div": "Divehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; nedre",
|
"dsb": "Sorbian; nedre",
|
||||||
|
"dse": "Nederländskt teckenspråk",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Hollänska; medeltida (ca. 1050-1350)",
|
"dum": "Hollänska; medeltida (ca. 1050-1350)",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
@ -5994,6 +6401,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligaynon",
|
"hil": "Hiligaynon",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hettitiska språk",
|
"hit": "Hettitiska språk",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri Motu",
|
"hmo": "Hiri Motu",
|
||||||
"hrv": "Kroatiska",
|
"hrv": "Kroatiska",
|
||||||
@ -6303,12 +6711,12 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "Beyaz Rusça",
|
"bel": "Beyaz Rusça",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengalce",
|
"ben": "Bengalce",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bho": "Bhojpuri (Hindistan)",
|
"bho": "Bhojpuri (Hindistan)",
|
||||||
"bik": "Bikol (Filipinler)",
|
"bik": "Bikol (Filipinler)",
|
||||||
"byn": "Bilin",
|
"byn": "Bilin",
|
||||||
"bin": "Bini (Afrika)",
|
"bin": "Bini (Afrika)",
|
||||||
"bis": "Bislama (Vanuatu; Kuzey Pasifik)",
|
"bis": "Bislama (Vanuatu; Kuzey Pasifik)",
|
||||||
"berinomo": "Bit",
|
|
||||||
"zbl": "Blis Sembolleri",
|
"zbl": "Blis Sembolleri",
|
||||||
"bos": "Boşnakça",
|
"bos": "Boşnakça",
|
||||||
"bra": "Braj (Hindistan)",
|
"bra": "Braj (Hindistan)",
|
||||||
@ -6350,6 +6758,7 @@ LANGUAGE_NAMES = {
|
|||||||
"dgr": "Dogrib (Kanada)",
|
"dgr": "Dogrib (Kanada)",
|
||||||
"dua": "Duala (Afrika)",
|
"dua": "Duala (Afrika)",
|
||||||
"nld": "Flâmanca (Hollanda dili)",
|
"nld": "Flâmanca (Hollanda dili)",
|
||||||
|
"dse": "Hollandalı İşaret Dili",
|
||||||
"dyu": "Dyula (Burkina Faso; Mali)",
|
"dyu": "Dyula (Burkina Faso; Mali)",
|
||||||
"dzo": "Dzongkha (Butan)",
|
"dzo": "Dzongkha (Butan)",
|
||||||
"efi": "Efik (Afrika)",
|
"efi": "Efik (Afrika)",
|
||||||
@ -6378,6 +6787,7 @@ LANGUAGE_NAMES = {
|
|||||||
"lug": "Ganda Dili",
|
"lug": "Ganda Dili",
|
||||||
"gay": "Gayo (Sumatra)",
|
"gay": "Gayo (Sumatra)",
|
||||||
"gba": "Gbaya (Orta Afrika Cumhuriyeti)",
|
"gba": "Gbaya (Orta Afrika Cumhuriyeti)",
|
||||||
|
"hmj": "Ge",
|
||||||
"gez": "Geez (Etiyopya)",
|
"gez": "Geez (Etiyopya)",
|
||||||
"kat": "Gürcüce",
|
"kat": "Gürcüce",
|
||||||
"deu": "Almanca",
|
"deu": "Almanca",
|
||||||
@ -6680,11 +7090,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "білоруська",
|
"bel": "білоруська",
|
||||||
"bem": "бемба (Замбія)",
|
"bem": "бемба (Замбія)",
|
||||||
"ben": "бенгальська",
|
"ben": "бенгальська",
|
||||||
"berinomo": "біт",
|
|
||||||
"bho": "бходжпурі",
|
"bho": "бходжпурі",
|
||||||
"bik": "бікольська",
|
"bik": "бікольська",
|
||||||
"bin": "біні",
|
"bin": "біні",
|
||||||
"bis": "біслама",
|
"bis": "біслама",
|
||||||
|
"bit": "беріномо",
|
||||||
"bla": "сісіка",
|
"bla": "сісіка",
|
||||||
"bod": "тибетська",
|
"bod": "тибетська",
|
||||||
"bos": "боснійська",
|
"bos": "боснійська",
|
||||||
@ -6731,6 +7141,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "мальдивська",
|
"div": "мальдивська",
|
||||||
"doi": "догрі (макромова)",
|
"doi": "догрі (макромова)",
|
||||||
"dsb": "нижньолужицька",
|
"dsb": "нижньолужицька",
|
||||||
|
"dse": "голландська мова жестів",
|
||||||
"dua": "дуала",
|
"dua": "дуала",
|
||||||
"dum": "середньовічна голландська (бл. 1050-1350)",
|
"dum": "середньовічна голландська (бл. 1050-1350)",
|
||||||
"dyu": "діула",
|
"dyu": "діула",
|
||||||
@ -6793,6 +7204,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "хілігайнон",
|
"hil": "хілігайнон",
|
||||||
"hin": "хінді",
|
"hin": "хінді",
|
||||||
"hit": "хетська",
|
"hit": "хетська",
|
||||||
|
"hmj": "ге",
|
||||||
"hmn": "хмонг",
|
"hmn": "хмонг",
|
||||||
"hmo": "хірімоту",
|
"hmo": "хірімоту",
|
||||||
"hrv": "хорватська",
|
"hrv": "хорватська",
|
||||||
@ -7103,11 +7515,11 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "白俄罗斯语",
|
"bel": "白俄罗斯语",
|
||||||
"bem": "本巴语(赞比亚)",
|
"bem": "本巴语(赞比亚)",
|
||||||
"ben": "孟加拉语",
|
"ben": "孟加拉语",
|
||||||
"berinomo": "布兴话",
|
|
||||||
"bho": "博杰普尔语",
|
"bho": "博杰普尔语",
|
||||||
"bik": "比科尔语",
|
"bik": "比科尔语",
|
||||||
"bin": "比尼语",
|
"bin": "比尼语",
|
||||||
"bis": "比斯拉马语",
|
"bis": "比斯拉马语",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bla": "西克西卡语",
|
"bla": "西克西卡语",
|
||||||
"bod": "藏语",
|
"bod": "藏语",
|
||||||
"bos": "波斯尼亚语",
|
"bos": "波斯尼亚语",
|
||||||
@ -7154,6 +7566,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "迪维希语",
|
"div": "迪维希语",
|
||||||
"doi": "多格拉语",
|
"doi": "多格拉语",
|
||||||
"dsb": "索布语(下)",
|
"dsb": "索布语(下)",
|
||||||
|
"dse": "荷兰手语",
|
||||||
"dua": "杜亚拉语",
|
"dua": "杜亚拉语",
|
||||||
"dum": "荷兰语(中古,约 1050-1350)",
|
"dum": "荷兰语(中古,约 1050-1350)",
|
||||||
"dyu": "迪尤拉语",
|
"dyu": "迪尤拉语",
|
||||||
@ -7216,6 +7629,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "希利盖农语",
|
"hil": "希利盖农语",
|
||||||
"hin": "印地语",
|
"hin": "印地语",
|
||||||
"hit": "赫梯语",
|
"hit": "赫梯语",
|
||||||
|
"hmj": "亻革家语、重安江苗语",
|
||||||
"hmn": "苗语",
|
"hmn": "苗语",
|
||||||
"hmo": "希里莫图语",
|
"hmo": "希里莫图语",
|
||||||
"hrv": "克罗地亚语",
|
"hrv": "克罗地亚语",
|
||||||
@ -7525,12 +7939,12 @@ LANGUAGE_NAMES = {
|
|||||||
"bel": "白俄羅斯文",
|
"bel": "白俄羅斯文",
|
||||||
"bem": "Bemba (Zambia)",
|
"bem": "Bemba (Zambia)",
|
||||||
"ben": "Bengali",
|
"ben": "Bengali",
|
||||||
|
"bit": "Berinomo",
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"bik": "Bikol",
|
"bik": "Bikol",
|
||||||
"byn": "Bilin",
|
"byn": "Bilin",
|
||||||
"bin": "Bini",
|
"bin": "Bini",
|
||||||
"bis": "Bislama",
|
"bis": "Bislama",
|
||||||
"berinomo": "Bit",
|
|
||||||
"zbl": "布利斯符號",
|
"zbl": "布利斯符號",
|
||||||
"bos": "Bosnian",
|
"bos": "Bosnian",
|
||||||
"bra": "Braj",
|
"bra": "Braj",
|
||||||
@ -7572,6 +7986,7 @@ LANGUAGE_NAMES = {
|
|||||||
"dgr": "Dogrib",
|
"dgr": "Dogrib",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"nld": "荷蘭文",
|
"nld": "荷蘭文",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
"dzo": "Dzongkha",
|
"dzo": "Dzongkha",
|
||||||
"efi": "Efik",
|
"efi": "Efik",
|
||||||
@ -7600,6 +8015,7 @@ LANGUAGE_NAMES = {
|
|||||||
"lug": "Ganda",
|
"lug": "Ganda",
|
||||||
"gay": "Gayo",
|
"gay": "Gayo",
|
||||||
"gba": "Gbaya (Central African Republic)",
|
"gba": "Gbaya (Central African Republic)",
|
||||||
|
"hmj": "Ge",
|
||||||
"gez": "Geez",
|
"gez": "Geez",
|
||||||
"kat": "Georgian",
|
"kat": "Georgian",
|
||||||
"deu": "德文",
|
"deu": "德文",
|
||||||
@ -7954,6 +8370,7 @@ LANGUAGE_NAMES = {
|
|||||||
"div": "Dhivehi",
|
"div": "Dhivehi",
|
||||||
"doi": "Dogri (macrolanguage)",
|
"doi": "Dogri (macrolanguage)",
|
||||||
"dsb": "Sorbian; Lower",
|
"dsb": "Sorbian; Lower",
|
||||||
|
"dse": "Dutch Sign Language",
|
||||||
"dua": "Duala",
|
"dua": "Duala",
|
||||||
"dum": "Dutch; Middle (ca. 1050-1350)",
|
"dum": "Dutch; Middle (ca. 1050-1350)",
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
@ -8016,6 +8433,7 @@ LANGUAGE_NAMES = {
|
|||||||
"hil": "Hiligaynon",
|
"hil": "Hiligaynon",
|
||||||
"hin": "Hindi",
|
"hin": "Hindi",
|
||||||
"hit": "Hittite",
|
"hit": "Hittite",
|
||||||
|
"hmj": "Ge",
|
||||||
"hmn": "Hmong",
|
"hmn": "Hmong",
|
||||||
"hmo": "Hiri Motu",
|
"hmo": "Hiri Motu",
|
||||||
"hrv": "Croatian",
|
"hrv": "Croatian",
|
||||||
|
59
cps/kobo.py
59
cps/kobo.py
@ -23,11 +23,7 @@ import os
|
|||||||
import uuid
|
import uuid
|
||||||
from time import gmtime, strftime
|
from time import gmtime, strftime
|
||||||
import json
|
import json
|
||||||
|
from urllib.parse import unquote
|
||||||
try:
|
|
||||||
from urllib import unquote
|
|
||||||
except ImportError:
|
|
||||||
from urllib.parse import unquote
|
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Blueprint,
|
Blueprint,
|
||||||
@ -146,9 +142,16 @@ def HandleSyncRequest():
|
|||||||
if not current_app.wsgi_app.is_proxied:
|
if not current_app.wsgi_app.is_proxied:
|
||||||
log.debug('Kobo: Received unproxied request, changed request port to external server port')
|
log.debug('Kobo: Received unproxied request, changed request port to external server port')
|
||||||
|
|
||||||
new_books_last_modified = sync_token.books_last_modified
|
# if no books synced don't respect sync_token
|
||||||
new_books_last_created = sync_token.books_last_created
|
if not ub.session.query(ub.KoboSyncedBooks).filter(ub.KoboSyncedBooks.user_id == current_user.id).count():
|
||||||
|
sync_token.books_last_modified = datetime.datetime.min
|
||||||
|
sync_token.books_last_created = datetime.datetime.min
|
||||||
|
sync_token.reading_state_last_modified = datetime.datetime.min
|
||||||
|
|
||||||
|
new_books_last_modified = sync_token.books_last_modified # needed for sync selected shelfs only
|
||||||
|
new_books_last_created = sync_token.books_last_created # needed to distinguish between new and changed entitlement
|
||||||
new_reading_state_last_modified = sync_token.reading_state_last_modified
|
new_reading_state_last_modified = sync_token.reading_state_last_modified
|
||||||
|
|
||||||
new_archived_last_modified = datetime.datetime.min
|
new_archived_last_modified = datetime.datetime.min
|
||||||
sync_results = []
|
sync_results = []
|
||||||
|
|
||||||
@ -170,10 +173,10 @@ def HandleSyncRequest():
|
|||||||
ub.BookShelf.date_added,
|
ub.BookShelf.date_added,
|
||||||
ub.ArchivedBook.is_archived)
|
ub.ArchivedBook.is_archived)
|
||||||
changed_entries = (changed_entries
|
changed_entries = (changed_entries
|
||||||
.join(db.Data).outerjoin(ub.ArchivedBook, db.Books.id == ub.ArchivedBook.book_id)
|
.join(db.Data).outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id,
|
||||||
.join(ub.KoboSyncedBooks, ub.KoboSyncedBooks.book_id == db.Books.id, isouter=True)
|
ub.ArchivedBook.user_id == current_user.id))
|
||||||
.filter(or_(ub.KoboSyncedBooks.user_id != current_user.id,
|
.filter(db.Books.id.notin_(calibre_db.session.query(ub.KoboSyncedBooks.book_id)
|
||||||
ub.KoboSyncedBooks.book_id == None))
|
.filter(ub.KoboSyncedBooks.user_id == current_user.id)))
|
||||||
.filter(ub.BookShelf.date_added > sync_token.books_last_modified)
|
.filter(ub.BookShelf.date_added > sync_token.books_last_modified)
|
||||||
.filter(db.Data.format.in_(KOBO_FORMATS))
|
.filter(db.Data.format.in_(KOBO_FORMATS))
|
||||||
.filter(calibre_db.common_filters(allow_show_archived=True))
|
.filter(calibre_db.common_filters(allow_show_archived=True))
|
||||||
@ -193,11 +196,11 @@ def HandleSyncRequest():
|
|||||||
ub.ArchivedBook.last_modified,
|
ub.ArchivedBook.last_modified,
|
||||||
ub.ArchivedBook.is_archived)
|
ub.ArchivedBook.is_archived)
|
||||||
changed_entries = (changed_entries
|
changed_entries = (changed_entries
|
||||||
.join(db.Data).outerjoin(ub.ArchivedBook, db.Books.id == ub.ArchivedBook.book_id)
|
.join(db.Data).outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id,
|
||||||
.join(ub.KoboSyncedBooks, ub.KoboSyncedBooks.book_id == db.Books.id, isouter=True)
|
ub.ArchivedBook.user_id == current_user.id))
|
||||||
.filter(or_(ub.KoboSyncedBooks.user_id != current_user.id,
|
.filter(db.Books.id.notin_(calibre_db.session.query(ub.KoboSyncedBooks.book_id)
|
||||||
ub.KoboSyncedBooks.book_id == None))
|
.filter(ub.KoboSyncedBooks.user_id == current_user.id)))
|
||||||
.filter(calibre_db.common_filters())
|
.filter(calibre_db.common_filters(allow_show_archived=True))
|
||||||
.filter(db.Data.format.in_(KOBO_FORMATS))
|
.filter(db.Data.format.in_(KOBO_FORMATS))
|
||||||
.order_by(db.Books.last_modified)
|
.order_by(db.Books.last_modified)
|
||||||
.order_by(db.Books.id)
|
.order_by(db.Books.id)
|
||||||
@ -254,10 +257,12 @@ def HandleSyncRequest():
|
|||||||
if sqlalchemy_version2:
|
if sqlalchemy_version2:
|
||||||
max_change = calibre_db.session.execute(changed_entries
|
max_change = calibre_db.session.execute(changed_entries
|
||||||
.filter(ub.ArchivedBook.is_archived)
|
.filter(ub.ArchivedBook.is_archived)
|
||||||
|
.filter(ub.ArchivedBook.user_id == current_user.id)
|
||||||
.order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\
|
.order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\
|
||||||
.columns(db.Books).first()
|
.columns(db.Books).first()
|
||||||
else:
|
else:
|
||||||
max_change = changed_entries.from_self().filter(ub.ArchivedBook.is_archived) \
|
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()
|
.order_by(func.datetime(ub.ArchivedBook.last_modified).desc()).first()
|
||||||
|
|
||||||
max_change = max_change.last_modified if max_change else new_archived_last_modified
|
max_change = max_change.last_modified if max_change else new_archived_last_modified
|
||||||
@ -292,7 +297,8 @@ def HandleSyncRequest():
|
|||||||
|
|
||||||
changed_reading_states = changed_reading_states.filter(
|
changed_reading_states = changed_reading_states.filter(
|
||||||
and_(ub.KoboReadingState.user_id == current_user.id,
|
and_(ub.KoboReadingState.user_id == current_user.id,
|
||||||
ub.KoboReadingState.book_id.notin_(reading_states_in_new_entitlements)))
|
ub.KoboReadingState.book_id.notin_(reading_states_in_new_entitlements)))\
|
||||||
|
.order_by(ub.KoboReadingState.last_modified)
|
||||||
cont_sync |= bool(changed_reading_states.count() > SYNC_ITEM_LIMIT)
|
cont_sync |= bool(changed_reading_states.count() > SYNC_ITEM_LIMIT)
|
||||||
for kobo_reading_state in changed_reading_states.limit(SYNC_ITEM_LIMIT).all():
|
for kobo_reading_state in changed_reading_states.limit(SYNC_ITEM_LIMIT).all():
|
||||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == kobo_reading_state.book_id).one_or_none()
|
book = calibre_db.session.query(db.Books).filter(db.Books.id == kobo_reading_state.book_id).one_or_none()
|
||||||
@ -306,18 +312,19 @@ def HandleSyncRequest():
|
|||||||
|
|
||||||
sync_shelves(sync_token, sync_results, only_kobo_shelves)
|
sync_shelves(sync_token, sync_results, only_kobo_shelves)
|
||||||
|
|
||||||
|
# update last created timestamp to distinguish between new and changed entitlements
|
||||||
|
if not cont_sync:
|
||||||
sync_token.books_last_created = new_books_last_created
|
sync_token.books_last_created = new_books_last_created
|
||||||
sync_token.books_last_modified = new_books_last_modified
|
sync_token.books_last_modified = new_books_last_modified
|
||||||
sync_token.archive_last_modified = new_archived_last_modified
|
sync_token.archive_last_modified = new_archived_last_modified
|
||||||
sync_token.reading_state_last_modified = new_reading_state_last_modified
|
sync_token.reading_state_last_modified = new_reading_state_last_modified
|
||||||
# sync_token.books_last_id = books_last_id
|
|
||||||
|
|
||||||
return generate_sync_response(sync_token, sync_results, cont_sync)
|
return generate_sync_response(sync_token, sync_results, cont_sync)
|
||||||
|
|
||||||
|
|
||||||
def generate_sync_response(sync_token, sync_results, set_cont=False):
|
def generate_sync_response(sync_token, sync_results, set_cont=False):
|
||||||
extra_headers = {}
|
extra_headers = {}
|
||||||
if config.config_kobo_proxy:
|
if config.config_kobo_proxy and not set_cont:
|
||||||
# Merge in sync results from the official Kobo store.
|
# Merge in sync results from the official Kobo store.
|
||||||
try:
|
try:
|
||||||
store_response = make_request_to_kobo_store(sync_token)
|
store_response = make_request_to_kobo_store(sync_token)
|
||||||
@ -335,7 +342,7 @@ def generate_sync_response(sync_token, sync_results, set_cont=False):
|
|||||||
extra_headers["x-kobo-sync"] = "continue"
|
extra_headers["x-kobo-sync"] = "continue"
|
||||||
sync_token.to_headers(extra_headers)
|
sync_token.to_headers(extra_headers)
|
||||||
|
|
||||||
log.debug("Kobo Sync Content: {}".format(sync_results))
|
# log.debug("Kobo Sync Content: {}".format(sync_results))
|
||||||
# jsonify decodes the unicode string different to what kobo expects
|
# jsonify decodes the unicode string different to what kobo expects
|
||||||
response = make_response(json.dumps(sync_results), extra_headers)
|
response = make_response(json.dumps(sync_results), extra_headers)
|
||||||
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
@ -667,11 +674,8 @@ def HandleTagRemoveItem(tag_id):
|
|||||||
# Note: Public shelves that aren't owned by the user aren't supported.
|
# Note: Public shelves that aren't owned by the user aren't supported.
|
||||||
def sync_shelves(sync_token, sync_results, only_kobo_shelves=False):
|
def sync_shelves(sync_token, sync_results, only_kobo_shelves=False):
|
||||||
new_tags_last_modified = sync_token.tags_last_modified
|
new_tags_last_modified = sync_token.tags_last_modified
|
||||||
|
# transmit all archived shelfs independent of last sync (why should this matter?)
|
||||||
for shelf in ub.session.query(ub.ShelfArchive).filter(
|
for shelf in ub.session.query(ub.ShelfArchive).filter(ub.ShelfArchive.user_id == current_user.id):
|
||||||
func.datetime(ub.ShelfArchive.last_modified) > sync_token.tags_last_modified,
|
|
||||||
ub.ShelfArchive.user_id == current_user.id
|
|
||||||
):
|
|
||||||
new_tags_last_modified = max(shelf.last_modified, new_tags_last_modified)
|
new_tags_last_modified = max(shelf.last_modified, new_tags_last_modified)
|
||||||
sync_results.append({
|
sync_results.append({
|
||||||
"DeletedTag": {
|
"DeletedTag": {
|
||||||
@ -684,7 +688,6 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False):
|
|||||||
ub.session.delete(shelf)
|
ub.session.delete(shelf)
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
|
|
||||||
|
|
||||||
extra_filters = []
|
extra_filters = []
|
||||||
if only_kobo_shelves:
|
if only_kobo_shelves:
|
||||||
for shelf in ub.session.query(ub.Shelf).filter(
|
for shelf in ub.session.query(ub.Shelf).filter(
|
||||||
@ -847,7 +850,7 @@ def get_ub_read_status(kobo_read_status):
|
|||||||
|
|
||||||
def get_or_create_reading_state(book_id):
|
def get_or_create_reading_state(book_id):
|
||||||
book_read = ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id,
|
book_read = ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id,
|
||||||
ub.ReadBook.user_id == current_user.id).one_or_none()
|
ub.ReadBook.user_id == int(current_user.id)).one_or_none()
|
||||||
if not book_read:
|
if not book_read:
|
||||||
book_read = ub.ReadBook(user_id=current_user.id, book_id=book_id)
|
book_read = ub.ReadBook(user_id=current_user.id, book_id=book_id)
|
||||||
if not book_read.kobo_reading_state:
|
if not book_read.kobo_reading_state:
|
||||||
|
@ -62,6 +62,7 @@ particular calls to non-Kobo specific endpoints such as the CalibreWeb book down
|
|||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import urandom
|
from os import urandom
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from flask import g, Blueprint, url_for, abort, request
|
from flask import g, Blueprint, url_for, abort, request
|
||||||
from flask_login import login_user, current_user, login_required
|
from flask_login import login_user, current_user, login_required
|
||||||
@ -70,11 +71,6 @@ from flask_babel import gettext as _
|
|||||||
from . import logger, config, calibre_db, db, helper, ub, lm
|
from . import logger, config, calibre_db, db, helper, ub, lm
|
||||||
from .render_template import render_title_template
|
from .render_template import render_title_template
|
||||||
|
|
||||||
try:
|
|
||||||
from functools import wraps
|
|
||||||
except ImportError:
|
|
||||||
pass # We're not using Python 3
|
|
||||||
|
|
||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
|
||||||
@ -167,7 +163,7 @@ def generate_auth_token(user_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@kobo_auth.route("/deleteauthtoken/<int:user_id>")
|
@kobo_auth.route("/deleteauthtoken/<int:user_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_auth_token(user_id):
|
def delete_auth_token(user_id):
|
||||||
# Invalidate any prevously generated Kobo Auth token for this user.
|
# Invalidate any prevously generated Kobo Auth token for this user.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from . import ub
|
from . import ub
|
||||||
import datetime
|
import datetime
|
||||||
from sqlalchemy.sql.expression import or_, and_
|
from sqlalchemy.sql.expression import or_, and_, true
|
||||||
|
|
||||||
# Add the current book id to kobo_synced_books table for current user, if entry is already present,
|
# Add the current book id to kobo_synced_books table for current user, if entry is already present,
|
||||||
# do nothing (safety precaution)
|
# do nothing (safety precaution)
|
||||||
@ -36,9 +36,13 @@ def add_synced_books(book_id):
|
|||||||
|
|
||||||
|
|
||||||
# Select all entries of current book in kobo_synced_books table, which are from current user and delete them
|
# Select all entries of current book in kobo_synced_books table, which are from current user and delete them
|
||||||
def remove_synced_book(book_id):
|
def remove_synced_book(book_id, all=False):
|
||||||
|
if not all:
|
||||||
|
user = ub.KoboSyncedBooks.user_id == current_user.id
|
||||||
|
else:
|
||||||
|
user = true()
|
||||||
ub.session.query(ub.KoboSyncedBooks).filter(ub.KoboSyncedBooks.book_id == book_id) \
|
ub.session.query(ub.KoboSyncedBooks).filter(ub.KoboSyncedBooks.book_id == book_id) \
|
||||||
.filter(ub.KoboSyncedBooks.user_id == current_user.id).delete()
|
.filter(user).delete()
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
|
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ def change_archived_books(book_id, state=None, message=None):
|
|||||||
return archived_book.is_archived
|
return archived_book.is_archived
|
||||||
|
|
||||||
|
|
||||||
# select all books which are synced by the current user and do not belong to a synced shelf and them to archive
|
# select all books which are synced by the current user and do not belong to a synced shelf and set them to archive
|
||||||
# select all shelves from current user which are synced and do not belong to the "only sync" shelves
|
# select all shelves from current user which are synced and do not belong to the "only sync" shelves
|
||||||
def update_on_sync_shelfs(user_id):
|
def update_on_sync_shelfs(user_id):
|
||||||
books_to_archive = (ub.session.query(ub.KoboSyncedBooks)
|
books_to_archive = (ub.session.query(ub.KoboSyncedBooks)
|
||||||
@ -71,6 +75,7 @@ def update_on_sync_shelfs(user_id):
|
|||||||
.filter(ub.KoboSyncedBooks.user_id == user_id).delete()
|
.filter(ub.KoboSyncedBooks.user_id == user_id).delete()
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
|
|
||||||
|
# Search all shelf which are currently not synced
|
||||||
shelves_to_archive = ub.session.query(ub.Shelf).filter(ub.Shelf.user_id == user_id).filter(
|
shelves_to_archive = ub.session.query(ub.Shelf).filter(ub.Shelf.user_id == user_id).filter(
|
||||||
ub.Shelf.kobo_sync == 0).all()
|
ub.Shelf.kobo_sync == 0).all()
|
||||||
for a in shelves_to_archive:
|
for a in shelves_to_archive:
|
||||||
|
@ -42,22 +42,17 @@ logging.addLevelName(logging.CRITICAL, "CRIT")
|
|||||||
|
|
||||||
class _Logger(logging.Logger):
|
class _Logger(logging.Logger):
|
||||||
|
|
||||||
def debug_or_exception(self, message, *args, **kwargs):
|
def debug_or_exception(self, message, stacklevel=2, *args, **kwargs):
|
||||||
if sys.version_info > (3, 7):
|
if sys.version_info > (3, 7):
|
||||||
if is_debug_enabled():
|
if is_debug_enabled():
|
||||||
self.exception(message, stacklevel=2, *args, **kwargs)
|
self.exception(message, stacklevel=stacklevel, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
self.error(message, stacklevel=stacklevel, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
self.error(message, stacklevel=2, *args, **kwargs)
|
|
||||||
elif sys.version_info > (3, 0):
|
|
||||||
if is_debug_enabled():
|
if is_debug_enabled():
|
||||||
self.exception(message, stack_info=True, *args, **kwargs)
|
self.exception(message, stack_info=True, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
self.error(message, *args, **kwargs)
|
self.error(message, *args, **kwargs)
|
||||||
else:
|
|
||||||
if is_debug_enabled():
|
|
||||||
self.exception(message, *args, **kwargs)
|
|
||||||
else:
|
|
||||||
self.error(message, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def debug_no_auth(self, message, *args, **kwargs):
|
def debug_no_auth(self, message, *args, **kwargs):
|
||||||
|
@ -23,7 +23,6 @@ from scholarly import scholarly
|
|||||||
|
|
||||||
from cps.services.Metadata import MetaRecord, MetaSourceInfo, Metadata
|
from cps.services.Metadata import MetaRecord, MetaSourceInfo, Metadata
|
||||||
|
|
||||||
|
|
||||||
class scholar(Metadata):
|
class scholar(Metadata):
|
||||||
__name__ = "Google Scholar"
|
__name__ = "Google Scholar"
|
||||||
__id__ = "googlescholar"
|
__id__ = "googlescholar"
|
||||||
|
@ -27,10 +27,8 @@
|
|||||||
|
|
||||||
# http://flask.pocoo.org/snippets/62/
|
# http://flask.pocoo.org/snippets/62/
|
||||||
|
|
||||||
try:
|
from urllib.parse import urlparse, urljoin
|
||||||
from urllib.parse import urlparse, urljoin
|
|
||||||
except ImportError:
|
|
||||||
from urlparse import urlparse, urljoin
|
|
||||||
|
|
||||||
from flask import request, url_for, redirect
|
from flask import request, url_for, redirect
|
||||||
|
|
||||||
|
@ -21,11 +21,8 @@ import sys
|
|||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from jsonschema import validate, exceptions, __version__
|
from jsonschema import validate, exceptions, __version__
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
try:
|
|
||||||
# pylint: disable=unused-import
|
from urllib.parse import unquote
|
||||||
from urllib import unquote
|
|
||||||
except ImportError:
|
|
||||||
from urllib.parse import unquote
|
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
from .. import logger
|
from .. import logger
|
||||||
|
22
cps/shelf.py
22
cps/shelf.py
@ -56,7 +56,7 @@ def check_shelf_view_permissions(cur_shelf):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@shelf.route("/shelf/add/<int:shelf_id>/<int:book_id>")
|
@shelf.route("/shelf/add/<int:shelf_id>/<int:book_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def add_to_shelf(shelf_id, book_id):
|
def add_to_shelf(shelf_id, book_id):
|
||||||
xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
|
xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
|
||||||
@ -112,7 +112,7 @@ def add_to_shelf(shelf_id, book_id):
|
|||||||
return "", 204
|
return "", 204
|
||||||
|
|
||||||
|
|
||||||
@shelf.route("/shelf/massadd/<int:shelf_id>")
|
@shelf.route("/shelf/massadd/<int:shelf_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def search_to_shelf(shelf_id):
|
def search_to_shelf(shelf_id):
|
||||||
shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
||||||
@ -164,7 +164,7 @@ def search_to_shelf(shelf_id):
|
|||||||
return redirect(url_for('web.index'))
|
return redirect(url_for('web.index'))
|
||||||
|
|
||||||
|
|
||||||
@shelf.route("/shelf/remove/<int:shelf_id>/<int:book_id>")
|
@shelf.route("/shelf/remove/<int:shelf_id>/<int:book_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def remove_from_shelf(shelf_id, book_id):
|
def remove_from_shelf(shelf_id, book_id):
|
||||||
xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
|
xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
|
||||||
@ -248,12 +248,17 @@ def create_edit_shelf(shelf, page_title, page, shelf_id=False):
|
|||||||
if not current_user.role_edit_shelfs() and to_save.get("is_public") == "on":
|
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(_(u"Sorry you are not allowed to create a public shelf"), category="error")
|
||||||
return redirect(url_for('web.index'))
|
return redirect(url_for('web.index'))
|
||||||
shelf.is_public = 1 if to_save.get("is_public") else 0
|
is_public = 1 if to_save.get("is_public") else 0
|
||||||
if config.config_kobo_sync:
|
if config.config_kobo_sync:
|
||||||
shelf.kobo_sync = True if to_save.get("kobo_sync") else False
|
shelf.kobo_sync = True if to_save.get("kobo_sync") else False
|
||||||
|
if shelf.kobo_sync:
|
||||||
|
ub.session.query(ub.ShelfArchive).filter(ub.ShelfArchive.user_id == current_user.id).filter(
|
||||||
|
ub.ShelfArchive.uuid == shelf.uuid).delete()
|
||||||
|
ub.session_commit()
|
||||||
shelf_title = to_save.get("title", "")
|
shelf_title = to_save.get("title", "")
|
||||||
if check_shelf_is_unique(shelf, shelf_title, shelf_id):
|
if check_shelf_is_unique(shelf, shelf_title, is_public, shelf_id):
|
||||||
shelf.name = shelf_title
|
shelf.name = shelf_title
|
||||||
|
shelf.is_public = is_public
|
||||||
if not shelf_id:
|
if not shelf_id:
|
||||||
shelf.user_id = int(current_user.id)
|
shelf.user_id = int(current_user.id)
|
||||||
ub.session.add(shelf)
|
ub.session.add(shelf)
|
||||||
@ -284,12 +289,12 @@ def create_edit_shelf(shelf, page_title, page, shelf_id=False):
|
|||||||
sync_only_selected_shelves=sync_only_selected_shelves)
|
sync_only_selected_shelves=sync_only_selected_shelves)
|
||||||
|
|
||||||
|
|
||||||
def check_shelf_is_unique(shelf, title, shelf_id=False):
|
def check_shelf_is_unique(shelf, title, is_public, shelf_id=False):
|
||||||
if shelf_id:
|
if shelf_id:
|
||||||
ident = ub.Shelf.id != shelf_id
|
ident = ub.Shelf.id != shelf_id
|
||||||
else:
|
else:
|
||||||
ident = true()
|
ident = true()
|
||||||
if shelf.is_public == 1:
|
if is_public == 1:
|
||||||
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
||||||
.filter((ub.Shelf.name == title) & (ub.Shelf.is_public == 1)) \
|
.filter((ub.Shelf.name == title) & (ub.Shelf.is_public == 1)) \
|
||||||
.filter(ident) \
|
.filter(ident) \
|
||||||
@ -323,12 +328,13 @@ def delete_shelf_helper(cur_shelf):
|
|||||||
ub.session_commit("successfully deleted Shelf {}".format(cur_shelf.name))
|
ub.session_commit("successfully deleted Shelf {}".format(cur_shelf.name))
|
||||||
|
|
||||||
|
|
||||||
@shelf.route("/shelf/delete/<int:shelf_id>")
|
@shelf.route("/shelf/delete/<int:shelf_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_shelf(shelf_id):
|
def delete_shelf(shelf_id):
|
||||||
cur_shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
cur_shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
||||||
try:
|
try:
|
||||||
delete_shelf_helper(cur_shelf)
|
delete_shelf_helper(cur_shelf)
|
||||||
|
flash(_("Shelf successfully deleted"), category="success")
|
||||||
except InvalidRequestError:
|
except InvalidRequestError:
|
||||||
ub.session.rollback()
|
ub.session.rollback()
|
||||||
log.error("Settings DB is not Writeable")
|
log.error("Settings DB is not Writeable")
|
||||||
|
@ -429,7 +429,7 @@ div.log {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#detailcover { cursor:zoom-in; }
|
#detailcover { cursor:zoom-in; }
|
||||||
#detailcover:-webkit-full-screen { cursor:zoom-out; }
|
#detailcover:-webkit-full-screen { cursor:zoom-out; border: 0; }
|
||||||
#detailcover:-moz-full-screen { cursor:zoom-out; }
|
#detailcover:-moz-full-screen { cursor:zoom-out; border: 0; }
|
||||||
#detailcover:-ms-fullscreen { cursor:zoom-out; }
|
#detailcover:-ms-fullscreen { cursor:zoom-out; border: 0; }
|
||||||
#detailcover:fullscreen { cursor:zoom-out; }
|
#detailcover:fullscreen { cursor:zoom-out; border: 0; }
|
||||||
|
@ -62,7 +62,7 @@ $("#archived_cb").on("change", function() {
|
|||||||
$("#shelf-actions").on("click", "[data-shelf-action]", function (e) {
|
$("#shelf-actions").on("click", "[data-shelf-action]", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
$.get(this.href)
|
$.post(this.href)
|
||||||
.done(function() {
|
.done(function() {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
switch ($this.data("shelf-action")) {
|
switch ($this.data("shelf-action")) {
|
||||||
|
@ -47,7 +47,7 @@ $(function () {
|
|||||||
$("#tags").val(uniqueTags.join(", "));
|
$("#tags").val(uniqueTags.join(", "));
|
||||||
$("#languages").val(uniqueLanguages.join(", "));
|
$("#languages").val(uniqueLanguages.join(", "));
|
||||||
$("#rating").data("rating").setValue(Math.round(book.rating));
|
$("#rating").data("rating").setValue(Math.round(book.rating));
|
||||||
if(book.cover !== null){
|
if(book.cover && $("#cover_url").length){
|
||||||
$(".cover img").attr("src", book.cover);
|
$(".cover img").attr("src", book.cover);
|
||||||
$("#cover_url").val(book.cover);
|
$("#cover_url").val(book.cover);
|
||||||
}
|
}
|
||||||
@ -160,9 +160,7 @@ $(function () {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
keyword = $("#keyword").val();
|
keyword = $("#keyword").val();
|
||||||
$('.pill').each(function(){
|
$('.pill').each(function(){
|
||||||
// console.log($(this).data('control'));
|
|
||||||
$(this).data("initial", $(this).prop('checked'));
|
$(this).data("initial", $(this).prop('checked'));
|
||||||
// console.log($(this).data('initial'));
|
|
||||||
});
|
});
|
||||||
doSearch(keyword);
|
doSearch(keyword);
|
||||||
});
|
});
|
||||||
|
1
cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js
vendored
Normal file
1
cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(a){a.fn.datepicker.dates.ko={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],today:"오늘",clear:"삭제",format:"yyyy-mm-dd",titleFormat:"yyyy년mm월",weekStart:0}}(jQuery);
|
261
cps/static/js/libs/tinymce/langs/ko.js
Normal file
261
cps/static/js/libs/tinymce/langs/ko.js
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
tinymce.addI18n('ko_KR',{
|
||||||
|
"Redo": "\ub2e4\uc2dc\uc2e4\ud589",
|
||||||
|
"Undo": "\uc2e4\ud589\ucde8\uc18c",
|
||||||
|
"Cut": "\uc798\ub77c\ub0b4\uae30",
|
||||||
|
"Copy": "\ubcf5\uc0ac\ud558\uae30",
|
||||||
|
"Paste": "\ubd99\uc5ec\ub123\uae30",
|
||||||
|
"Select all": "\uc804\uccb4\uc120\ud0dd",
|
||||||
|
"New document": "\uc0c8 \ubb38\uc11c",
|
||||||
|
"Ok": "\ud655\uc778",
|
||||||
|
"Cancel": "\ucde8\uc18c",
|
||||||
|
"Visual aids": "\uc2dc\uac01\uad50\uc7ac",
|
||||||
|
"Bold": "\uad75\uac8c",
|
||||||
|
"Italic": "\uae30\uc6b8\uc784\uaf34",
|
||||||
|
"Underline": "\ubc11\uc904",
|
||||||
|
"Strikethrough": "\ucde8\uc18c\uc120",
|
||||||
|
"Superscript": "\uc717\ucca8\uc790",
|
||||||
|
"Subscript": "\uc544\ub798\ucca8\uc790",
|
||||||
|
"Clear formatting": "\ud3ec\ub9f7\ucd08\uae30\ud654",
|
||||||
|
"Align left": "\uc67c\ucabd\uc815\ub82c",
|
||||||
|
"Align center": "\uac00\uc6b4\ub370\uc815\ub82c",
|
||||||
|
"Align right": "\uc624\ub978\ucabd\uc815\ub82c",
|
||||||
|
"Justify": "\uc591\ucabd\uc815\ub82c",
|
||||||
|
"Bullet list": "\uc810\ub9ac\uc2a4\ud2b8",
|
||||||
|
"Numbered list": "\uc22b\uc790\ub9ac\uc2a4\ud2b8",
|
||||||
|
"Decrease indent": "\ub0b4\uc5b4\uc4f0\uae30",
|
||||||
|
"Increase indent": "\ub4e4\uc5ec\uc4f0\uae30",
|
||||||
|
"Close": "\ub2eb\uae30",
|
||||||
|
"Formats": "\ud3ec\ub9f7",
|
||||||
|
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\ube0c\ub77c\uc6b0\uc838\uac00 \ud074\ub9bd\ubcf4\ub4dc \uc811\uadfc\uc744 \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Ctrl+X\/C\/V \ud0a4\ub97c \uc774\uc6a9\ud574 \uc8fc\uc138\uc694.",
|
||||||
|
"Headers": "\uc2a4\ud0c0\uc77c",
|
||||||
|
"Header 1": "\uc81c\ubaa9 1",
|
||||||
|
"Header 2": "\uc81c\ubaa9 2",
|
||||||
|
"Header 3": "\uc81c\ubaa9 3",
|
||||||
|
"Header 4": "\uc81c\ubaa9 4",
|
||||||
|
"Header 5": "\uc81c\ubaa9 5",
|
||||||
|
"Header 6": "\uc81c\ubaa9 6",
|
||||||
|
"Headings": "\uc81c\ubaa9",
|
||||||
|
"Heading 1": "\uc81c\ubaa9 1",
|
||||||
|
"Heading 2": "\uc81c\ubaa9 2",
|
||||||
|
"Heading 3": "\uc81c\ubaa9 3",
|
||||||
|
"Heading 4": "\uc81c\ubaa9 4",
|
||||||
|
"Heading 5": "\uc81c\ubaa9 5",
|
||||||
|
"Heading 6": "\uc81c\ubaa9 6",
|
||||||
|
"Preformatted": "Preformatted",
|
||||||
|
"Div": "\uad6c\ubd84",
|
||||||
|
"Pre": "Pre",
|
||||||
|
"Code": "\ucf54\ub4dc",
|
||||||
|
"Paragraph": "\ub2e8\ub77d",
|
||||||
|
"Blockquote": "\uad6c\ud68d",
|
||||||
|
"Inline": "\ub77c\uc778 \uc124\uc815",
|
||||||
|
"Blocks": "\ube14\ub85d \uc124\uc815",
|
||||||
|
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\uc2a4\ud0c0\uc77c\ubcf5\uc0ac \ub044\uae30. \uc774 \uc635\uc158\uc744 \ub044\uae30 \uc804\uc5d0\ub294 \ubcf5\uc0ac \uc2dc, \uc2a4\ud0c0\uc77c\uc774 \ubcf5\uc0ac\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.",
|
||||||
|
"Font Family": "\uae00\uaf34",
|
||||||
|
"Font Sizes": "\ud3f0\ud2b8 \uc0ac\uc774\uc988",
|
||||||
|
"Class": "\ud074\ub798\uc2a4",
|
||||||
|
"Browse for an image": "\uc774\ubbf8\uc9c0 \ucc3e\uae30",
|
||||||
|
"OR": "\ud639\uc740",
|
||||||
|
"Drop an image here": "\uc774\ubbf8\uc9c0 \ub4dc\ub86d",
|
||||||
|
"Upload": "\uc5c5\ub85c\ub4dc",
|
||||||
|
"Block": "\ube14\ub85d",
|
||||||
|
"Align": "\uc815\ub82c",
|
||||||
|
"Default": "\uae30\ubcf8",
|
||||||
|
"Circle": "\uc6d0",
|
||||||
|
"Disc": "\uc6d0\ubc18",
|
||||||
|
"Square": "\uc0ac\uac01",
|
||||||
|
"Lower Alpha": "\uc54c\ud30c\ubcb3 \uc18c\ubb38\uc790",
|
||||||
|
"Lower Greek": "\uadf8\ub9ac\uc2a4\uc5b4 \uc18c\ubb38\uc790",
|
||||||
|
"Lower Roman": "\ub85c\ub9c8\uc790 \uc18c\ubb38\uc790",
|
||||||
|
"Upper Alpha": "\uc54c\ud30c\ubcb3 \uc18c\ubb38\uc790",
|
||||||
|
"Upper Roman": "\ub85c\ub9c8\uc790 \ub300\ubb38\uc790",
|
||||||
|
"Anchor": "\uc575\ucee4",
|
||||||
|
"Name": "\uc774\ub984",
|
||||||
|
"Id": "\uc544\uc774\ub514",
|
||||||
|
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\uc544\uc774\ub514\ub294 \ubb38\uc790, \uc22b\uc790, \ub300\uc2dc, \uc810, \ucf5c\ub860 \ub610\ub294 \ubc11\uc904\ub85c \uc2dc\uc791\ud574\uc57c\ud569\ub2c8\ub2e4.",
|
||||||
|
"You have unsaved changes are you sure you want to navigate away?": "\uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc815\ubcf4\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \ud398\uc774\uc9c0\ub97c \ubc97\uc5b4\ub098\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
|
||||||
|
"Restore last draft": "\ub9c8\uc9c0\ub9c9 \ucd08\uc548 \ubcf5\uc6d0",
|
||||||
|
"Special character": "\ud2b9\uc218\ubb38\uc790",
|
||||||
|
"Source code": "\uc18c\uc2a4\ucf54\ub4dc",
|
||||||
|
"Insert\/Edit code sample": "\ucf54\ub4dc\uc0d8\ud50c \uc0bd\uc785\/\ud3b8\uc9d1",
|
||||||
|
"Language": "\uc5b8\uc5b4",
|
||||||
|
"Code sample": "\ucf54\ub4dc\uc0d8\ud50c",
|
||||||
|
"Color": "\uc0c9\uc0c1",
|
||||||
|
"R": "R",
|
||||||
|
"G": "G",
|
||||||
|
"B": "B",
|
||||||
|
"Left to right": "\uc67c\ucabd\uc5d0\uc11c \uc624\ub978\ucabd",
|
||||||
|
"Right to left": "\uc624\ub978\ucabd\uc5d0\uc11c \uc67c\ucabd",
|
||||||
|
"Emoticons": "\uc774\ubaa8\ud2f0\ucf58",
|
||||||
|
"Document properties": "\ubb38\uc11c \uc18d\uc131",
|
||||||
|
"Title": "\uc81c\ubaa9",
|
||||||
|
"Keywords": "\ud0a4\uc6cc\ub4dc",
|
||||||
|
"Description": "\uc124\uba85",
|
||||||
|
"Robots": "\ub85c\ubd07",
|
||||||
|
"Author": "\uc800\uc790",
|
||||||
|
"Encoding": "\uc778\ucf54\ub529",
|
||||||
|
"Fullscreen": "\uc804\uccb4\ud654\uba74",
|
||||||
|
"Action": "\ub3d9\uc791",
|
||||||
|
"Shortcut": "\ub2e8\ucd95\ud0a4",
|
||||||
|
"Help": "\ub3c4\uc6c0\ub9d0",
|
||||||
|
"Address": "\uc8fc\uc18c",
|
||||||
|
"Focus to menubar": "\uba54\ub274\uc5d0 \ud3ec\ucee4\uc2a4",
|
||||||
|
"Focus to toolbar": "\ud234\ubc14\uc5d0 \ud3ec\ucee4\uc2a4",
|
||||||
|
"Focus to element path": "element path\uc5d0 \ud3ec\ucee4\uc2a4",
|
||||||
|
"Focus to contextual toolbar": "\ucf04\ud14d\uc2a4\ud2b8 \ud234\ubc14\uc5d0 \ud3ec\ucee4\uc2a4",
|
||||||
|
"Insert link (if link plugin activated)": "\ub9c1\ud06c \uc0bd\uc785 (link \ud50c\ub7ec\uadf8\uc778\uc774 \ud65c\uc131\ud654\ub41c \uc0c1\ud0dc\uc5d0\uc11c)",
|
||||||
|
"Save (if save plugin activated)": "\uc800\uc7a5 (save \ud50c\ub7ec\uadf8\uc778\uc774 \ud65c\uc131\ud654\ub41c \uc0c1\ud0dc\uc5d0\uc11c)",
|
||||||
|
"Find (if searchreplace plugin activated)": "\ucc3e\uae30(searchreplace \ud50c\ub7ec\uadf8\uc778\uc774 \ud65c\uc131\ud654\ub41c \uc0c1\ud0dc\uc5d0\uc11c)",
|
||||||
|
"Plugins installed ({0}):": "\uc124\uce58\ub41c \ud50c\ub7ec\uadf8\uc778 ({0}):",
|
||||||
|
"Premium plugins:": "\uace0\uae09 \ud50c\ub7ec\uadf8\uc778",
|
||||||
|
"Learn more...": "\uc880 \ub354 \uc0b4\ud3b4\ubcf4\uae30",
|
||||||
|
"You are using {0}": "{0}\ub97c \uc0ac\uc6a9\uc911",
|
||||||
|
"Plugins": "\ud50c\ub7ec\uadf8\uc778",
|
||||||
|
"Handy Shortcuts": "\ub2e8\ucd95\ud0a4",
|
||||||
|
"Horizontal line": "\uac00\ub85c",
|
||||||
|
"Insert\/edit image": "\uc774\ubbf8\uc9c0 \uc0bd\uc785\/\uc218\uc815",
|
||||||
|
"Image description": "\uc774\ubbf8\uc9c0 \uc124\uba85",
|
||||||
|
"Source": "\uc18c\uc2a4",
|
||||||
|
"Dimensions": "\ud06c\uae30",
|
||||||
|
"Constrain proportions": "\uc791\uc5c5 \uc81c\ud55c",
|
||||||
|
"General": "\uc77c\ubc18",
|
||||||
|
"Advanced": "\uace0\uae09",
|
||||||
|
"Style": "\uc2a4\ud0c0\uc77c",
|
||||||
|
"Vertical space": "\uc218\uc9c1 \uacf5\ubc31",
|
||||||
|
"Horizontal space": "\uc218\ud3c9 \uacf5\ubc31",
|
||||||
|
"Border": "\ud14c\ub450\ub9ac",
|
||||||
|
"Insert image": "\uc774\ubbf8\uc9c0 \uc0bd\uc785",
|
||||||
|
"Image": "\uc774\ubbf8\uc9c0",
|
||||||
|
"Image list": "\uc774\ubbf8\uc9c0 \ubaa9\ub85d",
|
||||||
|
"Rotate counterclockwise": "\uc2dc\uacc4\ubc18\ub300\ubc29\ud5a5\uc73c\ub85c \ud68c\uc804",
|
||||||
|
"Rotate clockwise": "\uc2dc\uacc4\ubc29\ud5a5\uc73c\ub85c \ud68c\uc804",
|
||||||
|
"Flip vertically": "\uc218\uc9c1 \ub4a4\uc9d1\uae30",
|
||||||
|
"Flip horizontally": "\uc218\ud3c9 \ub4a4\uc9d1\uae30",
|
||||||
|
"Edit image": "\uc774\ubbf8\uc9c0 \ud3b8\uc9d1",
|
||||||
|
"Image options": "\uc774\ubbf8\uc9c0 \uc635\uc158",
|
||||||
|
"Zoom in": "\ud655\ub300",
|
||||||
|
"Zoom out": "\ucd95\uc18c",
|
||||||
|
"Crop": "\uc790\ub974\uae30",
|
||||||
|
"Resize": "\ud06c\uae30 \uc870\uc808",
|
||||||
|
"Orientation": "\ubc29\ud5a5",
|
||||||
|
"Brightness": "\ubc1d\uae30",
|
||||||
|
"Sharpen": "\uc120\uba85\ud558\uac8c",
|
||||||
|
"Contrast": "\ub300\ube44",
|
||||||
|
"Color levels": "\uc0c9\uc0c1\ub808\ubca8",
|
||||||
|
"Gamma": "\uac10\ub9c8",
|
||||||
|
"Invert": "\ubc18\uc804",
|
||||||
|
"Apply": "\uc801\uc6a9",
|
||||||
|
"Back": "\ub4a4\ub85c",
|
||||||
|
"Insert date\/time": "\ub0a0\uc9dc\/\uc2dc\uac04\uc0bd\uc785",
|
||||||
|
"Date\/time": "\ub0a0\uc9dc\/\uc2dc\uac04",
|
||||||
|
"Insert link": "\ub9c1\ud06c \uc0bd\uc785 ",
|
||||||
|
"Insert\/edit link": "\ub9c1\ud06c \uc0bd\uc785\/\uc218\uc815",
|
||||||
|
"Text to display": "\ubcf8\ubb38",
|
||||||
|
"Url": "\uc8fc\uc18c",
|
||||||
|
"Target": "\ub300\uc0c1",
|
||||||
|
"None": "\uc5c6\uc74c",
|
||||||
|
"New window": "\uc0c8\ucc3d",
|
||||||
|
"Remove link": "\ub9c1\ud06c\uc0ad\uc81c",
|
||||||
|
"Anchors": "\ucc45\uac08\ud53c",
|
||||||
|
"Link": "\ub9c1\ud06c",
|
||||||
|
"Paste or type a link": "\ub9c1\ud06c\ub97c \ubd99\uc5ec\ub123\uac70\ub098 \uc785\ub825\ud558\uc138\uc694",
|
||||||
|
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\ud604\uc7ac E-mail\uc8fc\uc18c\ub97c \uc785\ub825\ud558\uc168\uc2b5\ub2c8\ub2e4. E-mail \uc8fc\uc18c\uc5d0 \ub9c1\ud06c\ub97c \uac78\uae4c\uc694?",
|
||||||
|
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\ud604\uc7ac \uc6f9\uc0ac\uc774\ud2b8 \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uc168\uc2b5\ub2c8\ub2e4. \ud574\ub2f9 \uc8fc\uc18c\uc5d0 \ub9c1\ud06c\ub97c \uac78\uae4c\uc694?",
|
||||||
|
"Link list": "\ub9c1\ud06c \ub9ac\uc2a4\ud2b8",
|
||||||
|
"Insert video": "\ube44\ub514\uc624 \uc0bd\uc785",
|
||||||
|
"Insert\/edit video": "\ube44\ub514\uc624 \uc0bd\uc785\/\uc218\uc815",
|
||||||
|
"Insert\/edit media": "\ubbf8\ub514\uc5b4 \uc0bd\uc785\/\uc218\uc815",
|
||||||
|
"Alternative source": "\ub300\uccb4 \uc18c\uc2a4",
|
||||||
|
"Poster": "\ud3ec\uc2a4\ud130",
|
||||||
|
"Paste your embed code below:": "\uc544\ub798\uc5d0 \ucf54\ub4dc\ub97c \ubd99\uc5ec\ub123\uc73c\uc138\uc694:",
|
||||||
|
"Embed": "\uc0bd\uc785",
|
||||||
|
"Media": "\ubbf8\ub514\uc5b4",
|
||||||
|
"Nonbreaking space": "\ub744\uc5b4\uc4f0\uae30",
|
||||||
|
"Page break": "\ud398\uc774\uc9c0 \uad6c\ubd84\uc790",
|
||||||
|
"Paste as text": "\ud14d\uc2a4\ud2b8\ub85c \ubd99\uc5ec\ub123\uae30",
|
||||||
|
"Preview": "\ubbf8\ub9ac\ubcf4\uae30",
|
||||||
|
"Print": "\ucd9c\ub825",
|
||||||
|
"Save": "\uc800\uc7a5",
|
||||||
|
"Find": "\ucc3e\uae30",
|
||||||
|
"Replace with": "\uad50\uccb4",
|
||||||
|
"Replace": "\uad50\uccb4",
|
||||||
|
"Replace all": "\uc804\uccb4 \uad50\uccb4",
|
||||||
|
"Prev": "\uc774\uc804",
|
||||||
|
"Next": "\ub2e4\uc74c",
|
||||||
|
"Find and replace": "\ucc3e\uc544\uc11c \uad50\uccb4",
|
||||||
|
"Could not find the specified string.": "\ubb38\uc790\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
|
||||||
|
"Match case": "\ub300\uc18c\ubb38\uc790 \uc77c\uce58",
|
||||||
|
"Whole words": "\uc804\uccb4 \ub2e8\uc5b4",
|
||||||
|
"Spellcheck": "\ubb38\ubc95\uccb4\ud06c",
|
||||||
|
"Ignore": "\ubb34\uc2dc",
|
||||||
|
"Ignore all": "\uc804\uccb4\ubb34\uc2dc",
|
||||||
|
"Finish": "\uc644\ub8cc",
|
||||||
|
"Add to Dictionary": "\uc0ac\uc804\uc5d0 \ucd94\uac00",
|
||||||
|
"Insert table": "\ud14c\uc774\ube14 \uc0bd\uc785",
|
||||||
|
"Table properties": "\ud14c\uc774\ube14 \uc18d\uc131",
|
||||||
|
"Delete table": "\ud14c\uc774\ube14 \uc0ad\uc81c",
|
||||||
|
"Cell": "\uc140",
|
||||||
|
"Row": "\uc5f4",
|
||||||
|
"Column": "\ud589",
|
||||||
|
"Cell properties": "\uc140 \uc18d",
|
||||||
|
"Merge cells": "\uc140 \ud569\uce58\uae30",
|
||||||
|
"Split cell": "\uc140 \ub098\ub204\uae30",
|
||||||
|
"Insert row before": "\uc774\uc804\uc5d0 \ud589 \uc0bd\uc785",
|
||||||
|
"Insert row after": "\ub2e4\uc74c\uc5d0 \ud589 \uc0bd\uc785",
|
||||||
|
"Delete row": "\ud589 \uc9c0\uc6b0\uae30",
|
||||||
|
"Row properties": "\ud589 \uc18d\uc131",
|
||||||
|
"Cut row": "\ud589 \uc798\ub77c\ub0b4\uae30",
|
||||||
|
"Copy row": "\ud589 \ubcf5\uc0ac",
|
||||||
|
"Paste row before": "\uc774\uc804\uc5d0 \ud589 \ubd99\uc5ec\ub123\uae30",
|
||||||
|
"Paste row after": "\ub2e4\uc74c\uc5d0 \ud589 \ubd99\uc5ec\ub123\uae30",
|
||||||
|
"Insert column before": "\uc774\uc804\uc5d0 \ud589 \uc0bd\uc785",
|
||||||
|
"Insert column after": "\ub2e4\uc74c\uc5d0 \uc5f4 \uc0bd\uc785",
|
||||||
|
"Delete column": "\uc5f4 \uc9c0\uc6b0\uae30",
|
||||||
|
"Cols": "\uc5f4",
|
||||||
|
"Rows": "\ud589",
|
||||||
|
"Width": "\ub113\uc774",
|
||||||
|
"Height": "\ub192\uc774",
|
||||||
|
"Cell spacing": "\uc140 \uac04\uaca9",
|
||||||
|
"Cell padding": "\uc140 \uc548\ucabd \uc5ec\ubc31",
|
||||||
|
"Caption": "\ucea1\uc158",
|
||||||
|
"Left": "\uc67c\ucabd",
|
||||||
|
"Center": "\uac00\uc6b4\ub370",
|
||||||
|
"Right": "\uc624\ub978\ucabd",
|
||||||
|
"Cell type": "\uc140 \ud0c0\uc785",
|
||||||
|
"Scope": "\ubc94\uc704",
|
||||||
|
"Alignment": "\uc815\ub82c",
|
||||||
|
"H Align": "\uac00\ub85c \uc815\ub82c",
|
||||||
|
"V Align": "\uc138\ub85c \uc815\ub82c",
|
||||||
|
"Top": "\uc0c1\ub2e8",
|
||||||
|
"Middle": "\uc911\uac04",
|
||||||
|
"Bottom": "\ud558\ub2e8",
|
||||||
|
"Header cell": "\ud5e4\ub354 \uc140",
|
||||||
|
"Row group": "\ud589 \uadf8\ub8f9",
|
||||||
|
"Column group": "\uc5f4 \uadf8\ub8f9",
|
||||||
|
"Row type": "\ud589 \ud0c0\uc785",
|
||||||
|
"Header": "\ud5e4\ub354",
|
||||||
|
"Body": "\ubc14\ub514",
|
||||||
|
"Footer": "\ud478\ud130",
|
||||||
|
"Border color": "\ud14c\ub450\ub9ac \uc0c9",
|
||||||
|
"Insert template": "\ud15c\ud50c\ub9bf \uc0bd\uc785",
|
||||||
|
"Templates": "\ud15c\ud50c\ub9bf",
|
||||||
|
"Template": "\ud15c\ud50c\ub9bf",
|
||||||
|
"Text color": "\ubb38\uc790 \uc0c9\uae54",
|
||||||
|
"Background color": "\ubc30\uacbd\uc0c9",
|
||||||
|
"Custom...": "\uc9c1\uc811 \uc0c9\uae54 \uc9c0\uc815\ud558\uae30",
|
||||||
|
"Custom color": "\uc9c1\uc811 \uc9c0\uc815\ud55c \uc0c9\uae54",
|
||||||
|
"No color": "\uc0c9\uc0c1 \uc5c6\uc74c",
|
||||||
|
"Table of Contents": "\ubaa9\ucc28",
|
||||||
|
"Show blocks": "\ube14\ub7ed \ubcf4\uc5ec\uc8fc\uae30",
|
||||||
|
"Show invisible characters": "\uc548\ubcf4\uc774\ub294 \ubb38\uc790 \ubcf4\uc774\uae30",
|
||||||
|
"Words: {0}": "\ub2e8\uc5b4: {0}",
|
||||||
|
"{0} words": "{0} \ub2e8\uc5b4",
|
||||||
|
"File": "\ud30c\uc77c",
|
||||||
|
"Edit": "\uc218\uc815",
|
||||||
|
"Insert": "\uc0bd\uc785",
|
||||||
|
"View": "\ubcf4\uae30",
|
||||||
|
"Format": "\ud3ec\ub9f7",
|
||||||
|
"Table": "\ud14c\uc774\ube14",
|
||||||
|
"Tools": "\ub3c4\uad6c",
|
||||||
|
"Powered by {0}": "Powered by {0}",
|
||||||
|
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\uc11c\uc2dd \uc788\ub294 \ud14d\uc2a4\ud2b8 \ud3b8\uc9d1\uae30 \uc785\ub2c8\ub2e4. ALT-F9\ub97c \ub204\ub974\uba74 \uba54\ub274, ALT-F10\ub97c \ub204\ub974\uba74 \ud234\ubc14, ALT-0\uc744 \ub204\ub974\uba74 \ub3c4\uc6c0\ub9d0\uc744 \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4."
|
||||||
|
});
|
@ -1,4 +1,4 @@
|
|||||||
tinymce.addI18n('zh_CN',{
|
tinymce.addI18n('zh_Hans_CN',{
|
||||||
"Redo": "\u91cd\u505a",
|
"Redo": "\u91cd\u505a",
|
||||||
"Undo": "\u64a4\u9500",
|
"Undo": "\u64a4\u9500",
|
||||||
"Cut": "\u526a\u5207",
|
"Cut": "\u526a\u5207",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
tinymce.addI18n('zh_TW',{
|
tinymce.addI18n('zh_Hant_TW',{
|
||||||
"Redo": "\u91cd\u505a",
|
"Redo": "\u91cd\u505a",
|
||||||
"Undo": "\u64a4\u92b7",
|
"Undo": "\u64a4\u92b7",
|
||||||
"Cut": "\u526a\u4e0b",
|
"Cut": "\u526a\u4e0b",
|
||||||
|
66
cps/static/js/main.js
Normal file → Executable file
66
cps/static/js/main.js
Normal file → Executable file
@ -20,6 +20,20 @@ function getPath() {
|
|||||||
return jsFileLocation.substr(0, jsFileLocation.search("/static/js/libs/jquery.min.js")); // the js folder path
|
return jsFileLocation.substr(0, jsFileLocation.search("/static/js/libs/jquery.min.js")); // the js folder path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function postButton(event, action){
|
||||||
|
event.preventDefault();
|
||||||
|
var newForm = jQuery('<form>', {
|
||||||
|
"action": action,
|
||||||
|
'target': "_top",
|
||||||
|
'method': "post"
|
||||||
|
}).append(jQuery('<input>', {
|
||||||
|
'name': 'csrf_token',
|
||||||
|
'value': $("input[name=\'csrf_token\']").val(),
|
||||||
|
'type': 'hidden'
|
||||||
|
})).appendTo('body');
|
||||||
|
newForm.submit();
|
||||||
|
}
|
||||||
|
|
||||||
function elementSorter(a, b) {
|
function elementSorter(a, b) {
|
||||||
a = +a.slice(0, -2);
|
a = +a.slice(0, -2);
|
||||||
b = +b.slice(0, -2);
|
b = +b.slice(0, -2);
|
||||||
@ -71,6 +85,22 @@ $(document).on("change", "select[data-controlall]", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*$(document).on("click", "#sendbtn", function (event) {
|
||||||
|
postButton(event, $(this).data('action'));
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".sendbutton", function (event) {
|
||||||
|
// $(".sendbutton").on("click", "body", function(event) {
|
||||||
|
postButton(event, $(this).data('action'));
|
||||||
|
});*/
|
||||||
|
|
||||||
|
$(document).on("click", ".postAction", function (event) {
|
||||||
|
// $(".sendbutton").on("click", "body", function(event) {
|
||||||
|
postButton(event, $(this).data('action'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Syntax has to be bind not on, otherwise problems with firefox
|
// Syntax has to be bind not on, otherwise problems with firefox
|
||||||
$(".container-fluid").bind("dragenter dragover", function () {
|
$(".container-fluid").bind("dragenter dragover", function () {
|
||||||
if($("#btn-upload").length && !$('body').hasClass('shelforder')) {
|
if($("#btn-upload").length && !$('body').hasClass('shelforder')) {
|
||||||
@ -168,7 +198,7 @@ function confirmDialog(id, dialogid, dataValue, yesFn, noFn) {
|
|||||||
$confirm.modal('show');
|
$confirm.modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#delete_confirm").click(function() {
|
$("#delete_confirm").click(function(event) {
|
||||||
//get data-id attribute of the clicked element
|
//get data-id attribute of the clicked element
|
||||||
var deleteId = $(this).data("delete-id");
|
var deleteId = $(this).data("delete-id");
|
||||||
var bookFormat = $(this).data("delete-format");
|
var bookFormat = $(this).data("delete-format");
|
||||||
@ -179,7 +209,7 @@ $("#delete_confirm").click(function() {
|
|||||||
if (ajaxResponse) {
|
if (ajaxResponse) {
|
||||||
path = getPath() + "/ajax/delete/" + deleteId;
|
path = getPath() + "/ajax/delete/" + deleteId;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"get",
|
method:"post",
|
||||||
url: path,
|
url: path,
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
success:function(data) {
|
success:function(data) {
|
||||||
@ -198,8 +228,7 @@ $("#delete_confirm").click(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
window.location.href = getPath() + "/delete/" + deleteId;
|
postButton(event, getPath() + "/delete/" + deleteId);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,9 +405,11 @@ $(function() {
|
|||||||
|
|
||||||
$("#restart").click(function() {
|
$("#restart").click(function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
method:"post",
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
url: window.location.pathname + "/../../shutdown",
|
url: getPath() + "/shutdown",
|
||||||
data: {"parameter":0},
|
data: JSON.stringify({"parameter":0}),
|
||||||
success: function success() {
|
success: function success() {
|
||||||
$("#spinner").show();
|
$("#spinner").show();
|
||||||
setTimeout(restartTimer, 3000);
|
setTimeout(restartTimer, 3000);
|
||||||
@ -387,9 +418,11 @@ $(function() {
|
|||||||
});
|
});
|
||||||
$("#shutdown").click(function() {
|
$("#shutdown").click(function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
method:"post",
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
url: window.location.pathname + "/../../shutdown",
|
url: getPath() + "/shutdown",
|
||||||
data: {"parameter":1},
|
data: JSON.stringify({"parameter":1}),
|
||||||
success: function success(data) {
|
success: function success(data) {
|
||||||
return alert(data.text);
|
return alert(data.text);
|
||||||
}
|
}
|
||||||
@ -447,9 +480,11 @@ $(function() {
|
|||||||
$("#DialogContent").html("");
|
$("#DialogContent").html("");
|
||||||
$("#spinner2").show();
|
$("#spinner2").show();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
method:"post",
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
url: getPath() + "/shutdown",
|
url: getPath() + "/shutdown",
|
||||||
data: {"parameter":2},
|
data: JSON.stringify({"parameter":2}),
|
||||||
success: function success(data) {
|
success: function success(data) {
|
||||||
$("#spinner2").hide();
|
$("#spinner2").hide();
|
||||||
$("#DialogContent").html(data.text);
|
$("#DialogContent").html(data.text);
|
||||||
@ -527,7 +562,7 @@ $(function() {
|
|||||||
$(this).data('value'),
|
$(this).data('value'),
|
||||||
function (value) {
|
function (value) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: "get",
|
method: "post",
|
||||||
url: getPath() + "/kobo_auth/deleteauthtoken/" + value,
|
url: getPath() + "/kobo_auth/deleteauthtoken/" + value,
|
||||||
});
|
});
|
||||||
$("#config_delete_kobo_token").hide();
|
$("#config_delete_kobo_token").hide();
|
||||||
@ -574,7 +609,7 @@ $(function() {
|
|||||||
function(value){
|
function(value){
|
||||||
path = getPath() + "/ajax/fullsync"
|
path = getPath() + "/ajax/fullsync"
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"get",
|
method:"post",
|
||||||
url: path,
|
url: path,
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
success:function(data) {
|
success:function(data) {
|
||||||
@ -679,13 +714,14 @@ $(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#delete_shelf").click(function() {
|
$("#delete_shelf").click(function(event) {
|
||||||
confirmDialog(
|
confirmDialog(
|
||||||
$(this).attr('id'),
|
$(this).attr('id'),
|
||||||
"GeneralDeleteModal",
|
"GeneralDeleteModal",
|
||||||
$(this).data('value'),
|
$(this).data('value'),
|
||||||
function(value){
|
function(value){
|
||||||
window.location.href = window.location.pathname + "/../../shelf/delete/" + value
|
postButton(event, $("#delete_shelf").data("action"));
|
||||||
|
// $("#delete_shelf").closest("form").submit()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -734,7 +770,8 @@ $(function() {
|
|||||||
$("#DialogContent").html("");
|
$("#DialogContent").html("");
|
||||||
$("#spinner2").show();
|
$("#spinner2").show();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"get",
|
method:"post",
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
url: getPath() + "/import_ldap_users",
|
url: getPath() + "/import_ldap_users",
|
||||||
success: function success(data) {
|
success: function success(data) {
|
||||||
@ -768,4 +805,3 @@ $(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,10 +62,13 @@ var reader;
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var csrftoken = $("input[name='csrf_token']").val();
|
||||||
|
|
||||||
// Save to database
|
// Save to database
|
||||||
$.ajax(calibre.bookmarkUrl, {
|
$.ajax(calibre.bookmarkUrl, {
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { bookmark: location || "" }
|
data: { bookmark: location || "" },
|
||||||
|
headers: { "X-CSRFToken": csrftoken }
|
||||||
}).fail(function (xhr, status, error) {
|
}).fail(function (xhr, status, error) {
|
||||||
alert(error);
|
alert(error);
|
||||||
});
|
});
|
||||||
|
@ -47,15 +47,15 @@ $(function() {
|
|||||||
var rows = rowsAfter;
|
var rows = rowsAfter;
|
||||||
|
|
||||||
if (e.type === "uncheck-all") {
|
if (e.type === "uncheck-all") {
|
||||||
rows = rowsBefore;
|
selections = [];
|
||||||
}
|
} else {
|
||||||
|
|
||||||
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
||||||
return row.id;
|
return row.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
var func = $.inArray(e.type, ["check", "check-all"]) > -1 ? "union" : "difference";
|
var func = $.inArray(e.type, ["check", "check-all"]) > -1 ? "union" : "difference";
|
||||||
selections = window._[func](selections, ids);
|
selections = window._[func](selections, ids);
|
||||||
|
}
|
||||||
if (selections.length >= 2) {
|
if (selections.length >= 2) {
|
||||||
$("#merge_books").removeClass("disabled");
|
$("#merge_books").removeClass("disabled");
|
||||||
$("#merge_books").attr("aria-disabled", false);
|
$("#merge_books").attr("aria-disabled", false);
|
||||||
@ -540,14 +540,14 @@ $(function() {
|
|||||||
var rows = rowsAfter;
|
var rows = rowsAfter;
|
||||||
|
|
||||||
if (e.type === "uncheck-all") {
|
if (e.type === "uncheck-all") {
|
||||||
rows = rowsBefore;
|
selections = [];
|
||||||
}
|
} else {
|
||||||
|
|
||||||
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
||||||
return row.id;
|
return row.id;
|
||||||
});
|
});
|
||||||
var func = $.inArray(e.type, ["check", "check-all"]) > -1 ? "union" : "difference";
|
var func = $.inArray(e.type, ["check", "check-all"]) > -1 ? "union" : "difference";
|
||||||
selections = window._[func](selections, ids);
|
selections = window._[func](selections, ids);
|
||||||
|
}
|
||||||
handle_header_buttons();
|
handle_header_buttons();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -217,13 +217,16 @@ class TaskConvert(CalibreTask):
|
|||||||
quotes.append(quotes_index)
|
quotes.append(quotes_index)
|
||||||
quotes_index += 1
|
quotes_index += 1
|
||||||
|
|
||||||
p = process_open(command, quotes)
|
p = process_open(command, quotes, newlines=False)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
return 1, _(u"Ebook-converter failed: %(error)s", error=e)
|
return 1, _(u"Ebook-converter failed: %(error)s", error=e)
|
||||||
|
|
||||||
while p.poll() is None:
|
while p.poll() is None:
|
||||||
nextline = p.stdout.readline()
|
nextline = p.stdout.readline()
|
||||||
log.debug(nextline.strip('\r\n'))
|
if isinstance(nextline, bytes):
|
||||||
|
nextline = nextline.decode('utf-8', errors="ignore").strip('\r\n')
|
||||||
|
if nextline:
|
||||||
|
log.debug(nextline)
|
||||||
# parse progress string from calibre-converter
|
# parse progress string from calibre-converter
|
||||||
progress = re.search(r"(\d+)%\s.*", nextline)
|
progress = re.search(r"(\d+)%\s.*", nextline)
|
||||||
if progress:
|
if progress:
|
||||||
@ -236,11 +239,15 @@ class TaskConvert(CalibreTask):
|
|||||||
calibre_traceback = p.stderr.readlines()
|
calibre_traceback = p.stderr.readlines()
|
||||||
error_message = ""
|
error_message = ""
|
||||||
for ele in calibre_traceback:
|
for ele in calibre_traceback:
|
||||||
log.debug(ele.strip('\n'))
|
ele = ele.decode('utf-8', errors="ignore").strip('\n')
|
||||||
|
log.debug(ele)
|
||||||
if not ele.startswith('Traceback') and not ele.startswith(' File'):
|
if not ele.startswith('Traceback') and not ele.startswith(' File'):
|
||||||
error_message = _("Calibre failed with error: %(error)s", error=ele.strip('\n'))
|
error_message = _("Calibre failed with error: %(error)s", error=ele)
|
||||||
return check, error_message
|
return check, error_message
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Convert"
|
return "Convert"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Convert {} {}".format(self.bookid, self.kindle_mail)
|
||||||
|
@ -158,10 +158,10 @@ class TaskEmail(CalibreTask):
|
|||||||
else:
|
else:
|
||||||
self.send_gmail_email(msg)
|
self.send_gmail_email(msg)
|
||||||
except MemoryError as e:
|
except MemoryError as e:
|
||||||
log.debug_or_exception(e)
|
log.debug_or_exception(e, stacklevel=3)
|
||||||
self._handleError(u'MemoryError sending e-mail: {}'.format(str(e)))
|
self._handleError(u'MemoryError sending e-mail: {}'.format(str(e)))
|
||||||
except (smtplib.SMTPException, smtplib.SMTPAuthenticationError) as e:
|
except (smtplib.SMTPException, smtplib.SMTPAuthenticationError) as e:
|
||||||
log.debug_or_exception(e)
|
log.debug_or_exception(e, stacklevel=3)
|
||||||
if hasattr(e, "smtp_error"):
|
if hasattr(e, "smtp_error"):
|
||||||
text = e.smtp_error.decode('utf-8').replace("\n", '. ')
|
text = e.smtp_error.decode('utf-8').replace("\n", '. ')
|
||||||
elif hasattr(e, "message"):
|
elif hasattr(e, "message"):
|
||||||
@ -171,11 +171,11 @@ class TaskEmail(CalibreTask):
|
|||||||
else:
|
else:
|
||||||
text = ''
|
text = ''
|
||||||
self._handleError(u'Smtplib Error sending e-mail: {}'.format(text))
|
self._handleError(u'Smtplib Error sending e-mail: {}'.format(text))
|
||||||
except socket.error as e:
|
except (socket.error) as e:
|
||||||
log.debug_or_exception(e)
|
log.debug_or_exception(e, stacklevel=3)
|
||||||
self._handleError(u'Socket Error sending e-mail: {}'.format(e.strerror))
|
self._handleError(u'Socket Error sending e-mail: {}'.format(e.strerror))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
log.debug_or_exception(ex)
|
log.debug_or_exception(ex, stacklevel=3)
|
||||||
self._handleError(u'Error sending e-mail: {}'.format(ex))
|
self._handleError(u'Error sending e-mail: {}'.format(ex))
|
||||||
|
|
||||||
def send_standard_email(self, msg):
|
def send_standard_email(self, msg):
|
||||||
@ -248,7 +248,7 @@ class TaskEmail(CalibreTask):
|
|||||||
data = file_.read()
|
data = file_.read()
|
||||||
file_.close()
|
file_.close()
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
log.debug_or_exception(e)
|
log.debug_or_exception(e, stacklevel=3)
|
||||||
log.error(u'The requested file could not be read. Maybe wrong permissions?')
|
log.error(u'The requested file could not be read. Maybe wrong permissions?')
|
||||||
return None
|
return None
|
||||||
# Set mimetype
|
# Set mimetype
|
||||||
@ -267,4 +267,4 @@ class TaskEmail(CalibreTask):
|
|||||||
return "E-mail"
|
return "E-mail"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{}, {}".format(self.name, self.subject)
|
return "E-mail {}, {}".format(self.name, self.subject)
|
||||||
|
@ -32,3 +32,6 @@ class TaskUpload(CalibreTask):
|
|||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Upload"
|
return "Upload"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Upload {}".format(self.message)
|
||||||
|
@ -188,9 +188,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{% if feature_support['updater'] %}
|
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
|
{% if feature_support['updater'] %}
|
||||||
<div class="hidden" id="update_error"> <span>{{update_error}}</span></div>
|
<div class="hidden" id="update_error"> <span>{{update_error}}</span></div>
|
||||||
<div class="btn btn-primary" id="check_for_update">{{_('Check for Update')}}</div>
|
<div class="btn btn-primary" id="check_for_update">{{_('Check for Update')}}</div>
|
||||||
<div class="btn btn-primary hidden" id="perform_update" data-toggle="modal" data-target="#StatusDialog">{{_('Perform Update')}}</div>
|
<div class="btn btn-primary hidden" id="perform_update" data-toggle="modal" data-target="#StatusDialog">{{_('Perform Update')}}</div>
|
||||||
|
@ -226,7 +226,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
<h4 class="modal-title" id="metaModalLabel">{{_('Fetch Metadata')}}</h4>
|
<h4 class="modal-title text-center" id="metaModalLabel">{{_('Fetch Metadata')}}</h4>
|
||||||
<form class="padded-bottom" id="meta-search">
|
<form class="padded-bottom" id="meta-search">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label class="sr-only" for="keyword">{{_('Keyword')}}</label>
|
<label class="sr-only" for="keyword">{{_('Keyword')}}</label>
|
||||||
@ -247,7 +247,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button>
|
<button id="meta_close" type="button" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -265,17 +265,17 @@
|
|||||||
>
|
>
|
||||||
<div class="media-body">
|
<div class="media-body">
|
||||||
<h4 class="media-heading">
|
<h4 class="media-heading">
|
||||||
<a href="<%= url %>" target="_blank" rel="noopener"><%= title %></a>
|
<a class="meta_title" href="<%= url %>" target="_blank" rel="noopener"><%= title %></a>
|
||||||
</h4>
|
</h4>
|
||||||
<p>{{_('Author')}}:<%= authors.join(" & ") %></p>
|
<p class="meta_author">{{_('Author')}}:<%= authors.join(" & ") %></p>
|
||||||
<% if (publisher) { %>
|
<% if (publisher) { %>
|
||||||
<p>{{_('Publisher')}}:<%= publisher %></p>
|
<p class="meta_publisher">{{_('Publisher')}}:<%= publisher %></p>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% if (description) { %>
|
<% if (description) { %>
|
||||||
<p>{{_('Description')}}: <%= description %></p>
|
<p class="meta_description">{{_('Description')}}: <%= description %></p>
|
||||||
<% } %>
|
<% } %>
|
||||||
<p>{{_('Source')}}:
|
<p>{{_('Source')}}:
|
||||||
<a href="<%= source.url %>" target="_blank" rel="noopener"><%= source.description %></a>
|
<a class="meta_source" href="<%= source.link %>" target="_blank" rel="noopener"><%= source.description %></a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -120,8 +120,8 @@
|
|||||||
<div class="text-left" id="merge_to"></div>
|
<div class="text-left" id="merge_to"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<input type="button" class="btn btn-danger" value="{{_('Merge')}}" name="merge_confirm" id="merge_confirm" data-dismiss="modal">
|
<input id="merge_confirm" type="button" class="btn btn-danger" value="{{_('Merge')}}" name="merge_confirm" id="merge_confirm" data-dismiss="modal">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
<button id="merge_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if g.user.kindle_mail and kindle_list %}
|
{% if g.user.kindle_mail and kindle_list %}
|
||||||
{% if kindle_list.__len__() == 1 %}
|
{% if kindle_list.__len__() == 1 %}
|
||||||
<a href="{{url_for('web.send_to_kindle', book_id=entry.id, book_format=kindle_list[0]['format'], convert=kindle_list[0]['convert'])}}" id="sendbtn" data-text="{{_('Send to Kindle')}}" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-send"></span> {{kindle_list[0]['text']}}</a>
|
<div id="sendbtn" data-action="{{url_for('web.send_to_kindle', book_id=entry.id, book_format=kindle_list[0]['format'], convert=kindle_list[0]['convert'])}}" data-text="{{_('Send to Kindle')}}" class="btn btn-primary postAction" role="button"><span class="glyphicon glyphicon-send"></span> {{kindle_list[0]['text']}}</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<button id="sendbtn2" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<button id="sendbtn2" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" aria-labelledby="send-to-kindle">
|
<ul class="dropdown-menu" aria-labelledby="send-to-kindle">
|
||||||
{% for format in kindle_list %}
|
{% for format in kindle_list %}
|
||||||
<li><a href="{{url_for('web.send_to_kindle', book_id=entry.id, book_format=format['format'], convert=format['convert'])}}">{{format['text']}}</a></li>
|
<li><a class="postAction" data-action="{{url_for('web.send_to_kindle', book_id=entry.id, book_format=format['format'], convert=format['convert'])}}">{{format['text']}}</a></li>
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="sidebar">
|
<div id="sidebar">
|
||||||
<div id="panels">
|
<div id="panels">
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
<!--input id="searchBox" placeholder="search" type="search"-->
|
<!--input id="searchBox" placeholder="search" type="search"-->
|
||||||
|
|
||||||
<!--a id="show-Search" class="show_view icon-search" data-view="Search">Search</a-->
|
<!--a id="show-Search" class="show_view icon-search" data-view="Search">Search</a-->
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<ul id="add-to-shelves" class="dropdown-menu" aria-labelledby="add-to-shelf">
|
<ul id="add-to-shelves" class="dropdown-menu" aria-labelledby="add-to-shelf">
|
||||||
{% for shelf in g.shelves_access %}
|
{% for shelf in g.shelves_access %}
|
||||||
{% if not shelf.is_public or g.user.role_edit_shelfs() %}
|
{% if not shelf.is_public or g.user.role_edit_shelfs() %}
|
||||||
<li><a href="{{ url_for('shelf.search_to_shelf', shelf_id=shelf.id) }}"> {{shelf.name}}{% if shelf.is_public == 1 %} {{_('(Public)')}}{% endif %}</a></li>
|
<li><a class="postAction" role="button" data-action="{{ url_for('shelf.search_to_shelf', shelf_id=shelf.id) }}"> {{shelf.name}}{% if shelf.is_public == 1 %} {{_('(Public)')}}{% endif %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -2,14 +2,16 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="discover">
|
<div class="discover">
|
||||||
<h2>{{title}}</h2>
|
<h2>{{title}}</h2>
|
||||||
|
<!--form method="post"--->
|
||||||
{% if g.user.role_download() %}
|
{% if g.user.role_download() %}
|
||||||
<a id="shelf_down" href="{{ url_for('shelf.show_simpleshelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Download') }} </a>
|
<a id="shelf_down" href="{{ url_for('shelf.show_simpleshelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Download') }} </a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if g.user.is_authenticated %}
|
{% if g.user.is_authenticated %}
|
||||||
{% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %}
|
{% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %}
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
<div class="btn btn-danger" id="delete_shelf" data-value="{{ shelf.id }}">{{ _('Delete this Shelf') }}</div>
|
<div class="btn btn-danger" data-action="{{url_for('shelf.delete_shelf', shelf_id=shelf.id)}}" id="delete_shelf" data-value="{{ shelf.id }}">{{ _('Delete this Shelf') }}</div>
|
||||||
<a id="edit_shelf" href="{{ url_for('shelf.edit_shelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Edit Shelf Properties') }} </a>
|
<a id="edit_shelf" href="{{ url_for('shelf.edit_shelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Edit Shelf Properties') }} </a>
|
||||||
|
</form>
|
||||||
{% if entries.__len__() %}
|
{% if entries.__len__() %}
|
||||||
<a id="order_shelf" href="{{ url_for('shelf.order_shelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Arrange books manually') }} </a>
|
<a id="order_shelf" href="{{ url_for('shelf.order_shelf', shelf_id=shelf.id) }}" class="btn btn-primary">{{ _('Arrange books manually') }} </a>
|
||||||
<button id="toggle_order_shelf" type="button" data-alt-text="{{ _('Disable Change order') }}" class="btn btn-primary">{{ _('Enable Change order') }}</button>
|
<button id="toggle_order_shelf" type="button" data-alt-text="{{ _('Disable Change order') }}" class="btn btn-primary">{{ _('Enable Change order') }}</button>
|
||||||
@ -84,22 +86,6 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--div id="DeleteShelfDialog" class="modal fade" role="dialog">
|
|
||||||
<div class="modal-dialog modal-sm">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header bg-danger text-center">
|
|
||||||
<span>{{_('Are you sure you want to delete this shelf?')}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body text-center">
|
|
||||||
<span>{{_('Shelf will be deleted for all users')}}</span>
|
|
||||||
<p></p>
|
|
||||||
<a id="confirm" href="{{ url_for('shelf.delete_shelf', shelf_id=shelf.id) }}" class="btn btn-danger">{{_('OK')}}</a>
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div-->
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block modal %}
|
{% block modal %}
|
||||||
{{ delete_confirm_modal() }}
|
{{ delete_confirm_modal() }}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
|
{% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
|
||||||
{% if g.user and g.user.role_admin() and not new_user and not profile and ( mail_configured and content.email if content.email != None ) %}
|
{% if g.user and g.user.role_admin() and not new_user and not profile and ( mail_configured and content.email if content.email != None ) %}
|
||||||
<a class="btn btn-default" id="resend_password" href="{{url_for('admin.reset_user_password', user_id = content.id) }}">{{_('Reset user Password')}}</a>
|
<a class="btn btn-default postAction" id="resend_password" role="button" data-action="{{url_for('admin.reset_user_password', user_id = content.id) }}">{{_('Reset user Password')}}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">{{_('Password')}}</label>
|
<label for="password">{{_('Password')}}</label>
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
cps/translations/ko/LC_MESSAGES/messages.mo
Normal file
BIN
cps/translations/ko/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
3174
cps/translations/ko/LC_MESSAGES/messages.po
Normal file
3174
cps/translations/ko/LC_MESSAGES/messages.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -421,8 +421,8 @@ class KoboReadingState(Base):
|
|||||||
book_id = Column(Integer)
|
book_id = Column(Integer)
|
||||||
last_modified = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
last_modified = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
||||||
priority_timestamp = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
priority_timestamp = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
||||||
current_bookmark = relationship("KoboBookmark", uselist=False, backref="kobo_reading_state", cascade="all")
|
current_bookmark = relationship("KoboBookmark", uselist=False, backref="kobo_reading_state", cascade="all, delete")
|
||||||
statistics = relationship("KoboStatistics", uselist=False, backref="kobo_reading_state", cascade="all")
|
statistics = relationship("KoboStatistics", uselist=False, backref="kobo_reading_state", cascade="all, delete")
|
||||||
|
|
||||||
|
|
||||||
class KoboBookmark(Base):
|
class KoboBookmark(Base):
|
||||||
|
@ -1055,7 +1055,8 @@ def get_tasks_status():
|
|||||||
return render_title_template('tasks.html', entries=answer, title=_(u"Tasks"), page="tasks")
|
return render_title_template('tasks.html', entries=answer, title=_(u"Tasks"), page="tasks")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/reconnect")
|
# method is available without login and not protected by CSRF to make it easy reachable
|
||||||
|
@app.route("/reconnect", methods=['GET'])
|
||||||
def reconnect():
|
def reconnect():
|
||||||
calibre_db.reconnect_db(config, ub.app_DB_path)
|
calibre_db.reconnect_db(config, ub.app_DB_path)
|
||||||
return json.dumps({})
|
return json.dumps({})
|
||||||
@ -1068,7 +1069,7 @@ def reconnect():
|
|||||||
def search():
|
def search():
|
||||||
term = request.args.get("query")
|
term = request.args.get("query")
|
||||||
if term:
|
if term:
|
||||||
return redirect(url_for('web.books_list', data="search", sort_param='stored', query=term))
|
return redirect(url_for('web.books_list', data="search", sort_param='stored', query=term.strip()))
|
||||||
else:
|
else:
|
||||||
return render_title_template('search.html',
|
return render_title_template('search.html',
|
||||||
searchterm="",
|
searchterm="",
|
||||||
@ -1435,7 +1436,7 @@ def download_link(book_id, book_format, anyname):
|
|||||||
return get_download_link(book_id, book_format, client)
|
return get_download_link(book_id, book_format, client)
|
||||||
|
|
||||||
|
|
||||||
@web.route('/send/<int:book_id>/<book_format>/<int:convert>')
|
@web.route('/send/<int:book_id>/<book_format>/<int:convert>', methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@download_required
|
@download_required
|
||||||
def send_to_kindle(book_id, book_format, convert):
|
def send_to_kindle(book_id, book_format, convert):
|
||||||
|
517
messages.pot
517
messages.pot
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ rsa>=3.4.2,<4.8.0
|
|||||||
six>=1.10.0,<1.17.0
|
six>=1.10.0,<1.17.0
|
||||||
|
|
||||||
# Gdrive and Gmail integration
|
# Gdrive and Gmail integration
|
||||||
google-api-python-client>=1.7.11,<2.32.0
|
google-api-python-client>=1.7.11,<2.34.0
|
||||||
|
|
||||||
# Gmail
|
# Gmail
|
||||||
google-auth-oauthlib>=0.4.3,<0.5.0
|
google-auth-oauthlib>=0.4.3,<0.5.0
|
||||||
@ -22,7 +22,7 @@ goodreads>=0.3.2,<0.4.0
|
|||||||
python-Levenshtein>=0.12.0,<0.13.0
|
python-Levenshtein>=0.12.0,<0.13.0
|
||||||
|
|
||||||
# ldap login
|
# ldap login
|
||||||
python-ldap>=3.0.0,<3.4.0
|
python-ldap>=3.0.0,<3.5.0
|
||||||
Flask-SimpleLDAP>=1.4.0,<1.5.0
|
Flask-SimpleLDAP>=1.4.0,<1.5.0
|
||||||
|
|
||||||
#oauth
|
#oauth
|
||||||
@ -31,7 +31,7 @@ SQLAlchemy-Utils>=0.33.5,<0.38.0
|
|||||||
|
|
||||||
# extracting metadata
|
# extracting metadata
|
||||||
rarfile>=2.7
|
rarfile>=2.7
|
||||||
scholarly>=1.2.0, <1.5
|
scholarly>=1.2.0, <1.6
|
||||||
markdown2==2.4.2
|
markdown2==2.4.2
|
||||||
html2text==2020.1.16
|
html2text==2020.1.16
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
@ -41,4 +41,4 @@ natsort>=2.2.0,<8.1.0
|
|||||||
comicapi>=2.2.0,<2.3.0
|
comicapi>=2.2.0,<2.3.0
|
||||||
|
|
||||||
#Kobo integration
|
#Kobo integration
|
||||||
jsonschema>=3.2.0,<4.3.0
|
jsonschema>=3.2.0,<4.4.0
|
||||||
|
26
setup.cfg
26
setup.cfg
@ -37,14 +37,14 @@ console_scripts =
|
|||||||
[options]
|
[options]
|
||||||
include_package_data = True
|
include_package_data = True
|
||||||
install_requires =
|
install_requires =
|
||||||
Babel>=1.3, <3.0
|
Babel>=1.3,<3.0
|
||||||
Flask-Babel>=0.11.1,<2.1.0
|
Flask-Babel>=0.11.1,<2.1.0
|
||||||
Flask-Login>=0.3.2,<0.5.1
|
Flask-Login>=0.3.2,<0.5.1
|
||||||
Flask-Principal>=0.3.2,<0.5.1
|
Flask-Principal>=0.3.2,<0.5.1
|
||||||
backports_abc>=0.4
|
backports_abc>=0.4
|
||||||
Flask>=1.0.2,<2.1.0
|
Flask>=1.0.2,<2.1.0
|
||||||
iso-639>=0.4.5,<0.5.0
|
iso-639>=0.4.5,<0.5.0
|
||||||
PyPDF3>=1.0.0,<1.0.4
|
PyPDF3>=1.0.0,<1.0.6
|
||||||
pytz>=2016.10
|
pytz>=2016.10
|
||||||
requests>=2.11.1,<2.25.0
|
requests>=2.11.1,<2.25.0
|
||||||
SQLAlchemy>=1.3.0,<1.5.0
|
SQLAlchemy>=1.3.0,<1.5.0
|
||||||
@ -52,42 +52,42 @@ install_requires =
|
|||||||
Wand>=0.4.4,<0.7.0
|
Wand>=0.4.4,<0.7.0
|
||||||
unidecode>=0.04.19,<1.3.0
|
unidecode>=0.04.19,<1.3.0
|
||||||
lxml>=3.8.0,<4.7.0
|
lxml>=3.8.0,<4.7.0
|
||||||
flask-wtf>=0.14.2,<0.16.0
|
flask-wtf>=0.14.2,<1.1.0
|
||||||
|
|
||||||
[options.extras_require]
|
[options.extras_require]
|
||||||
gdrive =
|
gdrive =
|
||||||
google-api-python-client>=1.7.11,<2.1.0
|
google-api-python-client>=1.7.11,<2.34.0
|
||||||
gevent>20.6.0,<22.0.0
|
gevent>20.6.0,<22.0.0
|
||||||
greenlet>=0.4.17,<1.2.0
|
greenlet>=0.4.17,<1.2.0
|
||||||
httplib2>=0.9.2,<0.20.0
|
httplib2>=0.9.2,<0.21.0
|
||||||
oauth2client>=4.0.0,<4.1.4
|
oauth2client>=4.0.0,<4.1.4
|
||||||
uritemplate>=3.0.0,<3.1.0
|
uritemplate>=3.0.0,<4.2.0
|
||||||
pyasn1-modules>=0.0.8,<0.3.0
|
pyasn1-modules>=0.0.8,<0.3.0
|
||||||
pyasn1>=0.1.9,<0.5.0
|
pyasn1>=0.1.9,<0.5.0
|
||||||
PyDrive2>=1.3.1,<1.9.0
|
PyDrive2>=1.3.1,<1.11.0
|
||||||
PyYAML>=3.12
|
PyYAML>=3.12
|
||||||
rsa>=3.4.2,<4.8.0
|
rsa>=3.4.2,<4.8.0
|
||||||
six>=1.10.0,<1.17.0
|
six>=1.10.0,<1.17.0
|
||||||
gmail =
|
gmail =
|
||||||
google-auth-oauthlib>=0.4.3,<0.5.0
|
google-auth-oauthlib>=0.4.3,<0.5.0
|
||||||
google-api-python-client>=1.7.11,<2.1.0
|
google-api-python-client>=1.7.11,<2.34.0
|
||||||
goodreads =
|
goodreads =
|
||||||
goodreads>=0.3.2,<0.4.0
|
goodreads>=0.3.2,<0.4.0
|
||||||
python-Levenshtein>=0.12.0,<0.13.0
|
python-Levenshtein>=0.12.0,<0.13.0
|
||||||
ldap =
|
ldap =
|
||||||
python-ldap>=3.0.0,<3.4.0
|
python-ldap>=3.0.0,<3.5.0
|
||||||
Flask-SimpleLDAP>=1.4.0,<1.5.0
|
Flask-SimpleLDAP>=1.4.0,<1.5.0
|
||||||
oauth =
|
oauth =
|
||||||
Flask-Dance>=2.0.0,<5.1.0
|
Flask-Dance>=2.0.0,<5.2.0
|
||||||
SQLAlchemy-Utils>=0.33.5,<0.38.0
|
SQLAlchemy-Utils>=0.33.5,<0.38.0
|
||||||
metadata =
|
metadata =
|
||||||
rarfile>=2.7
|
rarfile>=2.7
|
||||||
scholarly>=1.2.0,<1.3
|
scholarly>=1.2.0,<1.6
|
||||||
comics =
|
comics =
|
||||||
natsort>=2.2.0,<7.2.0
|
natsort>=2.2.0,<8.1.0
|
||||||
comicapi>= 2.2.0,<2.3.0
|
comicapi>= 2.2.0,<2.3.0
|
||||||
kobo =
|
kobo =
|
||||||
jsonschema>=3.2.0,<3.3.0
|
jsonschema>=3.2.0,<4.4.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user