Allow deleting books (fixes #119)

pull/181/head
OzzieIsaacs 7 years ago
parent daaee5b67e
commit cd0d450829

@ -25,8 +25,9 @@ Session = sessionmaker()
Session.configure(bind=engine) Session.configure(bind=engine)
session = scoped_session(Session) session = scoped_session(Session)
class GdriveId(Base): class GdriveId(Base):
__tablename__='gdrive_ids' __tablename__ = 'gdrive_ids'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
gdrive_id = Column(Integer, unique=True) gdrive_id = Column(Integer, unique=True)
@ -36,8 +37,9 @@ class GdriveId(Base):
def __repr__(self): def __repr__(self):
return str(self.path) return str(self.path)
class PermissionAdded(Base): class PermissionAdded(Base):
__tablename__='permissions_added' __tablename__ = 'permissions_added'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
gdrive_id = Column(Integer, unique=True) gdrive_id = Column(Integer, unique=True)
@ -45,15 +47,16 @@ class PermissionAdded(Base):
def __repr__(self): def __repr__(self):
return str(self.gdrive_id) return str(self.gdrive_id)
def migrate(): def migrate():
if not engine.dialect.has_table(engine.connect(), "permissions_added"): if not engine.dialect.has_table(engine.connect(), "permissions_added"):
PermissionAdded.__table__.create(bind = engine) PermissionAdded.__table__.create(bind = engine)
for sql in session.execute("select sql from sqlite_master where type='table'"): for sql in session.execute("select sql from sqlite_master where type='table'"):
if 'CREATE TABLE gdrive_ids' in sql[0]: if 'CREATE TABLE gdrive_ids' in sql[0]:
currUniqueConstraint='UNIQUE (gdrive_id)' currUniqueConstraint = 'UNIQUE (gdrive_id)'
if currUniqueConstraint in sql[0]: if currUniqueConstraint in sql[0]:
sql=sql[0].replace(currUniqueConstraint, 'UNIQUE (gdrive_id, path)') sql=sql[0].replace(currUniqueConstraint, 'UNIQUE (gdrive_id, path)')
sql=sql.replace(GdriveId.__tablename__, GdriveId.__tablename__+ '2') sql=sql.replace(GdriveId.__tablename__, GdriveId.__tablename__ + '2')
session.execute(sql) session.execute(sql)
session.execute('INSERT INTO gdrive_ids2 (id, gdrive_id, path) SELECT id, gdrive_id, path FROM gdrive_ids;') session.execute('INSERT INTO gdrive_ids2 (id, gdrive_id, path) SELECT id, gdrive_id, path FROM gdrive_ids;')
session.commit() session.commit()
@ -69,9 +72,10 @@ if not os.path.exists(dbpath):
migrate() migrate()
def getDrive(gauth=None): def getDrive(gauth=None):
if not gauth: if not gauth:
gauth=GoogleAuth(settings_file='settings.yaml') gauth = GoogleAuth(settings_file='settings.yaml')
# Try to load saved client credentials # Try to load saved client credentials
gauth.LoadCredentialsFile("gdrive_credentials") gauth.LoadCredentialsFile("gdrive_credentials")
if gauth.access_token_expired: if gauth.access_token_expired:
@ -83,126 +87,134 @@ def getDrive(gauth=None):
# Save the current credentials to a file # Save the current credentials to a file
return GoogleDrive(gauth) return GoogleDrive(gauth)
def getEbooksFolder(drive=None): def getEbooksFolder(drive=None):
if not drive: if not drive:
drive = getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
ebooksFolder= "title = '%s' and 'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % config.config_google_drive_folder ebooksFolder = "title = '%s' and 'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % config.config_google_drive_folder
fileList = drive.ListFile({'q': ebooksFolder}).GetList() fileList = drive.ListFile({'q': ebooksFolder}).GetList()
return fileList[0] return fileList[0]
def getEbooksFolderId(drive=None): def getEbooksFolderId(drive=None):
storedPathName=session.query(GdriveId).filter(GdriveId.path == '/').first() storedPathName = session.query(GdriveId).filter(GdriveId.path == '/').first()
if storedPathName: if storedPathName:
return storedPathName.gdrive_id return storedPathName.gdrive_id
else: else:
gDriveId=GdriveId() gDriveId = GdriveId()
gDriveId.gdrive_id=getEbooksFolder(drive)['id'] gDriveId.gdrive_id = getEbooksFolder(drive)['id']
gDriveId.path='/' gDriveId.path = '/'
session.merge(gDriveId) session.merge(gDriveId)
session.commit() session.commit()
return return
def getFolderInFolder(parentId, folderName, drive=None): def getFolderInFolder(parentId, folderName, drive=None):
if not drive: if not drive:
drive = getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
folder= "title = '%s' and '%s' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % (folderName.replace("'", "\\'"), parentId) folder = "title = '%s' and '%s' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % (folderName.replace("'", "\\'"), parentId)
fileList = drive.ListFile({'q': folder}).GetList() fileList = drive.ListFile({'q': folder}).GetList()
return fileList[0] return fileList[0]
def getFile(pathId, fileName, drive=None): def getFile(pathId, fileName, drive=None):
if not drive: if not drive:
drive = getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
metaDataFile="'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'")) metaDataFile = "'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'"))
fileList = drive.ListFile({'q': metaDataFile}).GetList() fileList = drive.ListFile({'q': metaDataFile}).GetList()
return fileList[0] return fileList[0]
def getFolderId(path, drive=None): def getFolderId(path, drive=None):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
currentFolderId=getEbooksFolderId(drive) currentFolderId = getEbooksFolderId(drive)
sqlCheckPath=path if path[-1] =='/' else path + '/' sqlCheckPath = path if path[-1] == '/' else path + '/'
storedPathName=session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first() storedPathName = session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first()
if not storedPathName: if not storedPathName:
dbChange=False dbChange = False
s=path.split('/') s = path.split('/')
for i, x in enumerate(s): for i, x in enumerate(s):
if len(x) > 0: if len(x) > 0:
currentPath="/".join(s[:i+1]) currentPath = "/".join(s[:i+1])
if currentPath[-1] != '/': if currentPath[-1] != '/':
currentPath = currentPath + '/' currentPath = currentPath + '/'
storedPathName=session.query(GdriveId).filter(GdriveId.path == currentPath).first() storedPathName = session.query(GdriveId).filter(GdriveId.path == currentPath).first()
if storedPathName: if storedPathName:
currentFolderId=storedPathName.gdrive_id currentFolderId = storedPathName.gdrive_id
else: else:
currentFolderId=getFolderInFolder(currentFolderId, x, drive)['id'] currentFolderId = getFolderInFolder(currentFolderId, x, drive)['id']
gDriveId=GdriveId() gDriveId = GdriveId()
gDriveId.gdrive_id=currentFolderId gDriveId.gdrive_id = currentFolderId
gDriveId.path=currentPath gDriveId.path = currentPath
session.merge(gDriveId) session.merge(gDriveId)
dbChange=True dbChange = True
if dbChange: if dbChange:
session.commit() session.commit()
else: else:
currentFolderId=storedPathName.gdrive_id currentFolderId = storedPathName.gdrive_id
return currentFolderId return currentFolderId
def getFileFromEbooksFolder(drive, path, fileName): def getFileFromEbooksFolder(drive, path, fileName):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
if path: if path:
# sqlCheckPath=path if path[-1] =='/' else path + '/' # sqlCheckPath=path if path[-1] =='/' else path + '/'
folderId=getFolderId(path, drive) folderId = getFolderId(path, drive)
else: else:
folderId=getEbooksFolderId(drive) folderId = getEbooksFolderId(drive)
return getFile(folderId, fileName, drive) return getFile(folderId, fileName, drive)
def copyDriveFileRemote(drive, origin_file_id, copy_title): def copyDriveFileRemote(drive, origin_file_id, copy_title):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
copied_file = {'title': copy_title} copied_file = {'title': copy_title}
try: try:
file_data = drive.auth.service.files().copy( file_data = drive.auth.service.files().copy(
fileId=origin_file_id, body=copied_file).execute() fileId = origin_file_id, body=copied_file).execute()
return drive.CreateFile({'id': file_data['id']}) return drive.CreateFile({'id': file_data['id']})
except errors.HttpError as error: except errors.HttpError as error:
print ('An error occurred: %s' % error) print ('An error occurred: %s' % error)
return None return None
def downloadFile(drive, path, filename, output): def downloadFile(drive, path, filename, output):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
f=getFileFromEbooksFolder(drive, path, filename) f = getFileFromEbooksFolder(drive, path, filename)
f.GetContentFile(output) f.GetContentFile(output)
def backupCalibreDbAndOptionalDownload(drive, f=None): def backupCalibreDbAndOptionalDownload(drive, f=None):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
metaDataFile="'%s' in parents and title = 'metadata.db' and trashed = false" % getEbooksFolderId() metaDataFile = "'%s' in parents and title = 'metadata.db' and trashed = false" % getEbooksFolderId()
fileList = drive.ListFile({'q': metaDataFile}).GetList() fileList = drive.ListFile({'q': metaDataFile}).GetList()
databaseFile=fileList[0] databaseFile = fileList[0]
if f: if f:
databaseFile.GetContentFile(f) databaseFile.GetContentFile(f)
@ -212,64 +224,65 @@ def copyToDrive(drive, uploadFile, createRoot, replaceFiles,
ignoreFiles=[], ignoreFiles=[],
parent=None, prevDir=''): parent=None, prevDir=''):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
isInitial=not bool(parent) isInitial = not bool(parent)
if not parent: if not parent:
parent=getEbooksFolder(drive) parent = getEbooksFolder(drive)
if os.path.isdir(os.path.join(prevDir,uploadFile)): if os.path.isdir(os.path.join(prevDir,uploadFile)):
existingFolder=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList() existingFolder = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
if len(existingFolder) == 0 and (not isInitial or createRoot): if len(existingFolder) == 0 and (not isInitial or createRoot):
parent = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], parent = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],
"mimeType": "application/vnd.google-apps.folder" }) "mimeType": "application/vnd.google-apps.folder"})
parent.Upload() parent.Upload()
else: else:
if (not isInitial or createRoot) and len(existingFolder) > 0: if (not isInitial or createRoot) and len(existingFolder) > 0:
parent=existingFolder[0] parent = existingFolder[0]
for f in os.listdir(os.path.join(prevDir,uploadFile)): for f in os.listdir(os.path.join(prevDir, uploadFile)):
if f not in ignoreFiles: if f not in ignoreFiles:
copyToDrive(drive, f, True, replaceFiles, ignoreFiles, parent, os.path.join(prevDir,uploadFile)) copyToDrive(drive, f, True, replaceFiles, ignoreFiles, parent, os.path.join(prevDir, uploadFile))
else: else:
if os.path.basename(uploadFile) not in ignoreFiles: if os.path.basename(uploadFile) not in ignoreFiles:
existingFiles=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList() existingFiles = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
if len(existingFiles) > 0: if len(existingFiles) > 0:
driveFile=existingFiles[0] driveFile = existingFiles[0]
else: else:
driveFile = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], }) driveFile = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents': [{"kind":"drive#fileLink", 'id': parent['id']}], })
driveFile.SetContentFile(os.path.join(prevDir,uploadFile)) driveFile.SetContentFile(os.path.join(prevDir, uploadFile))
driveFile.Upload() driveFile.Upload()
def uploadFileToEbooksFolder(drive, destFile, f): def uploadFileToEbooksFolder(drive, destFile, f):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
parent=getEbooksFolder(drive) parent = getEbooksFolder(drive)
splitDir=destFile.split('/') splitDir = destFile.split('/')
for i, x in enumerate(splitDir): for i, x in enumerate(splitDir):
if i == len(splitDir)-1: if i == len(splitDir)-1:
existingFiles=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList() existingFiles = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
if len(existingFiles) > 0: if len(existingFiles) > 0:
driveFile=existingFiles[0] driveFile = existingFiles[0]
else: else:
driveFile = drive.CreateFile({'title': x, 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], }) driveFile = drive.CreateFile({'title': x, 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],})
driveFile.SetContentFile(f) driveFile.SetContentFile(f)
driveFile.Upload() driveFile.Upload()
else: else:
existingFolder=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList() existingFolder = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
if len(existingFolder) == 0: if len(existingFolder) == 0:
parent = drive.CreateFile({'title': x, 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], parent = drive.CreateFile({'title': x, 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],
"mimeType": "application/vnd.google-apps.folder" }) "mimeType": "application/vnd.google-apps.folder"})
parent.Upload() parent.Upload()
else: else:
parent=existingFolder[0] parent = existingFolder[0]
def watchChange(drive, channel_id, channel_type, channel_address, def watchChange(drive, channel_id, channel_type, channel_address,
channel_token=None, expiration=None): channel_token=None, expiration=None):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
# Watch for all changes to a user's Drive. # Watch for all changes to a user's Drive.
@ -286,15 +299,16 @@ def watchChange(drive, channel_id, channel_type, channel_address,
# Raises: # Raises:
# apiclient.errors.HttpError: if http request to create channel fails. # apiclient.errors.HttpError: if http request to create channel fails.
body = { body = {
'id': channel_id, 'id': channel_id,
'type': channel_type, 'type': channel_type,
'address': channel_address 'address': channel_address
} }
if channel_token: if channel_token:
body['token'] = channel_token body['token'] = channel_token
if expiration: if expiration:
body['expiration'] = expiration body['expiration'] = expiration
return drive.auth.service.changes().watch(body=body).execute() return drive.auth.service.changes().watch(body=body).execute()
def watchFile(drive, file_id, channel_id, channel_type, channel_address, def watchFile(drive, file_id, channel_id, channel_type, channel_address,
channel_token=None, expiration=None): channel_token=None, expiration=None):
@ -314,7 +328,7 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
apiclient.errors.HttpError: if http request to create channel fails. apiclient.errors.HttpError: if http request to create channel fails.
""" """
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
@ -329,6 +343,7 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
body['expiration'] = expiration body['expiration'] = expiration
return drive.auth.service.files().watch(fileId=file_id, body=body).execute() return drive.auth.service.files().watch(fileId=file_id, body=body).execute()
def stopChannel(drive, channel_id, resource_id): def stopChannel(drive, channel_id, resource_id):
"""Stop watching to a specific channel. """Stop watching to a specific channel.
Args: Args:
@ -339,19 +354,20 @@ def stopChannel(drive, channel_id, resource_id):
apiclient.errors.HttpError: if http request to create channel fails. apiclient.errors.HttpError: if http request to create channel fails.
""" """
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
# service=drive.auth.service # service=drive.auth.service
body = { body = {
'id': channel_id, 'id': channel_id,
'resourceId': resource_id 'resourceId': resource_id
} }
return drive.auth.service.channels().stop(body=body).execute() return drive.auth.service.channels().stop(body=body).execute()
def getChangeById (drive, change_id): def getChangeById (drive, change_id):
if not drive: if not drive:
drive=getDrive() drive = getDrive()
if drive.auth.access_token_expired: if drive.auth.access_token_expired:
drive.auth.Refresh() drive.auth.Refresh()
# Print a single Change resource information. # Print a single Change resource information.

@ -38,6 +38,7 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
} }
.navbar-default .navbar-toggle .icon-bar {background-color: #000;} .navbar-default .navbar-toggle .icon-bar {background-color: #000;}
.navbar-default .navbar-toggle {border-color: #000;} .navbar-default .navbar-toggle {border-color: #000;}
.cover { margin-bottom: 10px;}
.btn-file {position: relative; overflow: hidden;} .btn-file {position: relative; overflow: hidden;}
.btn-file input[type=file] {position: absolute; top: 0; right: 0; min-width: 100%; min-height: 100%; font-size: 100px; text-align: right; filter: alpha(opacity=0); opacity: 0; outline: none; background: white; cursor: inherit; display: block;} .btn-file input[type=file] {position: absolute; top: 0; right: 0; min-width: 100%; min-height: 100%; font-size: 100px; text-align: right; filter: alpha(opacity=0); opacity: 0; outline: none; background: white; cursor: inherit; display: block;}

@ -1,17 +1,23 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block body %} {% block body %}
{% if book %} {% if book %}
<div class="col-sm-3 col-lg-3 col-xs-12"> <form role="form" action="{{ url_for('edit_book', book_id=book.id) }}" method="post">
<div class="cover">
{% if book.has_cover %} <div class="col-sm-3 col-lg-3 col-xs-12">
<img src="{{ url_for('get_cover', cover_path=book.path.replace('\\','/')) }}" /> <div class="cover">
{% else %} {% if book.has_cover %}
<img src="{{ url_for('static', filename='generic_cover.jpg') }}" /> <img src="{{ url_for('get_cover', cover_path=book.path.replace('\\','/')) }}" />
{% endif %} {% else %}
<img src="{{ url_for('static', filename='generic_cover.jpg') }}" />
{% endif %}
</div>
{% if g.user.role_delete_books() %}
<div class="text-center">
<button type="button" class="btn btn-danger" id="delete" data-toggle="modal" data-target="#deleteModal">{{_("Delete Book")}}</button>
</div>
{% endif %}
</div> </div>
</div> <div class="col-sm-9 col-xs-12">
<div class="col-sm-8">
<form role="form" action="{{ url_for('edit_book', book_id=book.id) }}" method="post">
<div class="form-group"> <div class="form-group">
<label for="book_title">{{_('Book Title')}}</label> <label for="book_title">{{_('Book Title')}}</label>
<input type="text" class="form-control" name="book_title" id="book_title" value="{{book.title}}"> <input type="text" class="form-control" name="book_title" id="book_title" value="{{book.title}}">
@ -107,9 +113,31 @@
<a href="#" id="get_meta" class="btn btn-default" data-toggle="modal" data-target="#metaModal">{{_('Get metadata')}}</a> <a href="#" id="get_meta" class="btn btn-default" data-toggle="modal" data-target="#metaModal">{{_('Get metadata')}}</a>
<button type="submit" class="btn btn-default">{{_('Submit')}}</button> <button type="submit" class="btn btn-default">{{_('Submit')}}</button>
<a href="{{ url_for('show_book', book_id=book.id) }}" class="btn btn-default">{{_('Back')}}</a> <a href="{{ url_for('show_book', book_id=book.id) }}" class="btn btn-default">{{_('Back')}}</a>
</form> </div>
</form>
{% endif %}
{% if g.user.role_delete_books() %}
<div class="modal fade" id="deleteModal" role="dialog" aria-labelledby="metaDeleteLabel">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-danger text-center">
<span>{{_('Are really you sure?')}}</span>
</div>
<div class="modal-body text-center" id="meta-info">
<span>{{_('Book will be deleted from Calibre database')}}</span>
<span>{{_('and from hard disk')}}</span>
</div>
<div class="modal-footer">
<a href="{{ url_for('delete_book', book_id=book.id) }}" class="btn btn-danger">{{_('Delete')}}</a>
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button>
</div>
</div>
</div>
</div> </div>
{% endif %} {% endif %}
<div class="modal fade" id="metaModal" tabindex="-1" role="dialog" aria-labelledby="metaModalLabel"> <div class="modal fade" id="metaModal" tabindex="-1" role="dialog" aria-labelledby="metaModalLabel">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">

@ -110,6 +110,10 @@
<input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}> <input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
<label for="edit_role">{{_('Allow Edit')}}</label> <label for="edit_role">{{_('Allow Edit')}}</label>
</div> </div>
<div class="form-group">
<input type="checkbox" name="delete_role" id="delete_role" {% if content.role_delete_books() %}checked{% endif %}>
<label for="delete_role">{{_('Allow Delete books')}}</label>
</div>
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}> <input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}>
<label for="passwd_role">{{_('Allow Changing Password')}}</label> <label for="passwd_role">{{_('Allow Changing Password')}}</label>

@ -98,6 +98,10 @@
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}> <input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
<label for="edit_role">{{_('Allow Edit')}}</label> <label for="edit_role">{{_('Allow Edit')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="delete_role" id="delete_role" {% if content.role_delete_books() %}checked{% endif %}>
<label for="delete_role">{{_('Allow Delete books')}}</label>
</div> </div>
{% if not content.role_anonymous() %} {% if not content.role_anonymous() %}
<div class="form-group"> <div class="form-group">

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Calibre-web\n" "Project-Id-Version: Calibre-web\n"
"Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: 2016-07-12 19:54+0200\n" "PO-Revision-Date: 2016-07-12 19:54+0200\n"
"Last-Translator: Ozzie Isaacs\n" "Last-Translator: Ozzie Isaacs\n"
"Language: de\n" "Language: de\n"
@ -32,7 +32,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "Nicht installiert" msgstr "Nicht installiert"
@ -63,329 +63,333 @@ msgstr ""
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "Konnte .epub nicht nach .mobi konvertieren" msgstr "Konnte .epub nicht nach .mobi konvertieren"
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "Gast" msgstr "Gast"
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "Frage Update Paket an" msgstr "Frage Update Paket an"
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "Lade Update Paket herunter" msgstr "Lade Update Paket herunter"
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "Entpacke Update Paket" msgstr "Entpacke Update Paket"
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "Ersetze Dateien" msgstr "Ersetze Dateien"
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "Schließe Datenbankverbindungen" msgstr "Schließe Datenbankverbindungen"
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "Stoppe Server" msgstr "Stoppe Server"
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "Update abgeschlossen, bitte okay drücken und Seite neu laden" msgstr "Update abgeschlossen, bitte okay drücken und Seite neu laden"
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "Letzte Bücher" msgstr "Letzte Bücher"
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "Beliebte Bücher (die meisten Downloads)" msgstr "Beliebte Bücher (die meisten Downloads)"
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "Best bewertete Bücher" msgstr "Best bewertete Bücher"
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "Zufällige Bücher" msgstr "Zufällige Bücher"
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "Autorenliste" msgstr "Autorenliste"
#: cps/web.py:1048 #: cps/web.py:1072
#, python-format #, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "Autor: %(name)s" msgstr "Autor: %(name)s"
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "" msgstr ""
"Buch öffnen fehlgeschlagen. Datei existiert nicht, oder ist nicht " "Buch öffnen fehlgeschlagen. Datei existiert nicht, oder ist nicht "
"zugänglich." "zugänglich."
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "Liste Serien" msgstr "Liste Serien"
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "Serie: %(serie)s" msgstr "Serie: %(serie)s"
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "Verfügbare Sprachen" msgstr "Verfügbare Sprachen"
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "Sprache: %(name)s" msgstr "Sprache: %(name)s"
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "Kategorieliste" msgstr "Kategorieliste"
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "Kategorie: %(name)s" msgstr "Kategorie: %(name)s"
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "Statistiken" msgstr "Statistiken"
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "Server neu gestartet,bitte Seite neu laden" msgstr "Server neu gestartet,bitte Seite neu laden"
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "Server wird runtergefahren, bitte Fenster schließen" msgstr "Server wird runtergefahren, bitte Fenster schließen"
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "Update durchgeführt" msgstr "Update durchgeführt"
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "Suche" msgstr "Suche"
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "Lese ein Buch" msgstr "Lese ein Buch"
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "Bitte alle Felder ausfüllen!" msgstr "Bitte alle Felder ausfüllen!"
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "Registieren" msgstr "Registieren"
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen." msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen."
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "Der Benutzername oder die E-Mailadresse ist in bereits in Benutzung." msgstr "Der Benutzername oder die E-Mailadresse ist in bereits in Benutzung."
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "Du bist nun eingeloggt als '%(nickname)s'" msgstr "Du bist nun eingeloggt als '%(nickname)s'"
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "Falscher Benutzername oder Passwort" msgstr "Falscher Benutzername oder Passwort"
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "Login" msgstr "Login"
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "Bitte zuerst die SMTP Mail Einstellung konfigurieren ..." msgstr "Bitte zuerst die SMTP Mail Einstellung konfigurieren ..."
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "Buch erfolgreich versandt an %(kindlemail)s" msgstr "Buch erfolgreich versandt an %(kindlemail)s"
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "Beim Senden des Buchs trat ein Fehler auf: %(res)s" msgstr "Beim Senden des Buchs trat ein Fehler auf: %(res)s"
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "Bitte die Kindle E-Mail Adresse zuuerst konfigurieren..." msgstr "Bitte die Kindle E-Mail Adresse zuuerst konfigurieren..."
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "Das Buch wurde dem Bücherregal: %(sname)s hinzugefügt" msgstr "Das Buch wurde dem Bücherregal: %(sname)s hinzugefügt"
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "Das Buch wurde aus dem Bücherregal: %(sname)s entfernt" msgstr "Das Buch wurde aus dem Bücherregal: %(sname)s entfernt"
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "Es existiert bereits ein Bücheregal mit dem Titel '%(title)s'" msgstr "Es existiert bereits ein Bücheregal mit dem Titel '%(title)s'"
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "Bücherregal %(title)s erzeugt" msgstr "Bücherregal %(title)s erzeugt"
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "Es trat ein Fehler auf" msgstr "Es trat ein Fehler auf"
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "Bücherregal erzeugen" msgstr "Bücherregal erzeugen"
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "Bücherregal %(title)s verändert" msgstr "Bücherregal %(title)s verändert"
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "Bücherregal editieren" msgstr "Bücherregal editieren"
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "Bücherregal %(name)s erfolgreich gelöscht" msgstr "Bücherregal %(name)s erfolgreich gelöscht"
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "Bücherregal: '%(name)s'" msgstr "Bücherregal: '%(name)s'"
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "Reihenfolge in Bücherregal '%(name)s' verändern" msgstr "Reihenfolge in Bücherregal '%(name)s' verändern"
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "Es existiert ein Benutzerkonto für diese E-Mailadresse" msgstr "Es existiert ein Benutzerkonto für diese E-Mailadresse"
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "%(name)s's Profil" msgstr "%(name)s's Profil"
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "Profil aktualisiert" msgstr "Profil aktualisiert"
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "Admin Seite" msgstr "Admin Seite"
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "Calibre-web Konfiguration wurde aktualisiert" msgstr "Calibre-web Konfiguration wurde aktualisiert"
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "Basis Konfiguration" msgstr "Basis Konfiguration"
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "DB Speicherort ist ungültig, bitte Pfad korrigieren" msgstr "DB Speicherort ist ungültig, bitte Pfad korrigieren"
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "Neuen Benutzer hinzufügen" msgstr "Neuen Benutzer hinzufügen"
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "Benutzer '%(user)s' angelegt" msgstr "Benutzer '%(user)s' angelegt"
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "" msgstr ""
"Es existiert ein Benutzerkonto für diese Emailadresse oder den " "Es existiert ein Benutzerkonto für diese Emailadresse oder den "
"Benutzernamen." "Benutzernamen."
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "E-Mail Einstellungen aktualisiert" msgstr "E-Mail Einstellungen aktualisiert"
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "Test E-Mail erfolgreich an %(kindlemail)s versendet" msgstr "Test E-Mail erfolgreich an %(kindlemail)s versendet"
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "Fehler beim versenden der Test E-Mail: %(res)s" msgstr "Fehler beim versenden der Test E-Mail: %(res)s"
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "E-Mail Einstellungen wurde aktualisiert" msgstr "E-Mail Einstellungen wurde aktualisiert"
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "E-Mail Einstellungen editieren" msgstr "E-Mail Einstellungen editieren"
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "Benutzer '%(nick)s' gelöscht" msgstr "Benutzer '%(nick)s' gelöscht"
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "Benutzer '%(nick)s' aktualisiert" msgstr "Benutzer '%(nick)s' aktualisiert"
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "Es ist ein unbekanter Fehler aufgetreten" msgstr "Es ist ein unbekanter Fehler aufgetreten"
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "Benutzer %(nick)s bearbeiten" msgstr "Benutzer %(nick)s bearbeiten"
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr "Unbekannt"
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "Metadaten editieren" msgstr "Metadaten editieren"
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "Die Dateiendung \"%s\" kann nicht auf diesen Server hochgeladen werden" msgstr "Die Dateiendung \"%s\" kann nicht auf diesen Server hochgeladen werden"
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "Datei müssen eine Erweiterung haben, um hochgeladen zu werden" msgstr "Datei müssen eine Erweiterung haben, um hochgeladen zu werden"
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "Fehler beim Erzeugen des Pfads %s (Zugriff verweigert)" msgstr "Fehler beim Erzeugen des Pfads %s (Zugriff verweigert)"
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "Fehler beim speichern der Datei %s (Zugriff verweigert)" msgstr "Fehler beim speichern der Datei %s (Zugriff verweigert)"
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "Fehler beim Löschen von Datei %s (Zugriff verweigert)" msgstr "Fehler beim Löschen von Datei %s (Zugriff verweigert)"
@ -536,10 +540,10 @@ msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "Zurück" msgstr "Zurück"
@ -551,104 +555,124 @@ msgstr "Calibre-web wirklich stoppen"
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "Updatevorgang, bitte Seite nicht neu laden" msgstr "Updatevorgang, bitte Seite nicht neu laden"
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr "Buch löschen"
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "Buchtitel" msgstr "Buchtitel"
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "Autor" msgstr "Autor"
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "Tags" msgstr "Tags"
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "Serien" msgstr "Serien"
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "Serien ID" msgstr "Serien ID"
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "Bewertung" msgstr "Bewertung"
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "Cover URL (jpg)" msgstr "Cover URL (jpg)"
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "Sprache" msgstr "Sprache"
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "Ja" msgstr "Ja"
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "Nein" msgstr "Nein"
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "Buch nach Bearbeitung ansehen" msgstr "Buch nach Bearbeitung ansehen"
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "Metadaten laden" msgstr "Metadaten laden"
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "Abschicken" msgstr "Abschicken"
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr "Sicher?"
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr "Das Buch wird aus der Calibre Datenbank"
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr "und der Festplatte gelöscht"
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr "Löschen"
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "Suchbegriff" msgstr "Suchbegriff"
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr "Suchbegriff" msgstr "Suchbegriff"
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "Los!" msgstr "Los!"
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "Klicke auf das Bild um die Metadaten zu übertragen" msgstr "Klicke auf das Bild um die Metadaten zu übertragen"
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "Lade..." msgstr "Lade..."
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "Fehler bei Suche!" msgstr "Fehler bei Suche!"
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "Kein Ergebniss! Bitte anderen Begriff versuchen" msgstr "Kein Ergebniss! Bitte anderen Begriff versuchen"
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "Herausgeber" msgstr "Herausgeber"
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "Quelle" msgstr "Quelle"
@ -732,15 +756,19 @@ msgstr "Uploads erlauben"
msgid "Allow Edit" msgid "Allow Edit"
msgstr "Bearbeiten erlauben" msgstr "Bearbeiten erlauben"
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Delete books"
msgstr "Bücher löschen erlauben"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "Passwort ändern erlauben" msgstr "Passwort ändern erlauben"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr "Öffentliche Bücherregale editieren erlauben"
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "Login" msgstr "Login"
@ -1021,11 +1049,11 @@ msgstr "Reihenfolge ändern"
#: cps/templates/shelf.html:47 #: cps/templates/shelf.html:47
msgid "Do you really want to delete the shelf?" msgid "Do you really want to delete the shelf?"
msgstr "" msgstr "Wirklich das Bücherregal löschen?"
#: cps/templates/shelf.html:50 #: cps/templates/shelf.html:50
msgid "Shelf will be lost for everybody and forever!" msgid "Shelf will be lost for everybody and forever!"
msgstr "" msgstr "Das Bücherregal wird für alle und für immer gelöscht"
#: cps/templates/shelf_edit.html:13 #: cps/templates/shelf_edit.html:13
msgid "should the shelf be public?" msgid "should the shelf be public?"
@ -1115,11 +1143,11 @@ msgstr "Zeige Gelesen/Ungelesen Auswahl"
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "Zeige zufällige Bücher in der Detailansicht" msgstr "Zeige zufällige Bücher in der Detailansicht"
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "Benutzer löschen" msgstr "Benutzer löschen"
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "Letzte Downloads" msgstr "Letzte Downloads"

@ -14,7 +14,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Calibre-web\n" "Project-Id-Version: Calibre-web\n"
"Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: 2017-04-04 15:09+0200\n" "PO-Revision-Date: 2017-04-04 15:09+0200\n"
"Last-Translator: Juan F. Villa <juan.villa@paisdelconocimiento.org>\n" "Last-Translator: Juan F. Villa <juan.villa@paisdelconocimiento.org>\n"
"Language: es\n" "Language: es\n"
@ -25,7 +25,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "No instalado" msgstr "No instalado"
@ -54,327 +54,331 @@ msgstr "Formato no compatible para enviar por correo electronico"
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "No fue posible convertir de epub a mobi" msgstr "No fue posible convertir de epub a mobi"
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "Invitado" msgstr "Invitado"
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "Solicitando paquete de actualización" msgstr "Solicitando paquete de actualización"
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "Descargando paquete de actualización" msgstr "Descargando paquete de actualización"
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "Descomprimiendo paquete de actualización" msgstr "Descomprimiendo paquete de actualización"
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "Ficheros sustituidos" msgstr "Ficheros sustituidos"
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "Los conexiones de base datos están cerradas" msgstr "Los conexiones de base datos están cerradas"
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "El servidor está detenido" msgstr "El servidor está detenido"
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "Actualización finalizada. Por favor, pulse OK y recargue la página" msgstr "Actualización finalizada. Por favor, pulse OK y recargue la página"
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "Libros recientes" msgstr "Libros recientes"
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "Libros populares (los mas descargados)" msgstr "Libros populares (los mas descargados)"
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "Libros mejor valorados" msgstr "Libros mejor valorados"
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "Libros al azar" msgstr "Libros al azar"
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "Lista de autores" msgstr "Lista de autores"
#: cps/web.py:1048 #: cps/web.py:1072
#, python-format #, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "Autor:%(name)s" msgstr "Autor:%(name)s"
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "Error en la apertura del eBook. El archivo no existe o no es accesible:" msgstr "Error en la apertura del eBook. El archivo no existe o no es accesible:"
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "Lista de series" msgstr "Lista de series"
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "Series : %(serie)s" msgstr "Series : %(serie)s"
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "Lenguajes disponibles" msgstr "Lenguajes disponibles"
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "Lenguaje: %(name)s" msgstr "Lenguaje: %(name)s"
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "Lista de categorias" msgstr "Lista de categorias"
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "Categoría : %(name)s" msgstr "Categoría : %(name)s"
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "Estadisticas" msgstr "Estadisticas"
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "Servidor reiniciado. Por favor, recargue la página" msgstr "Servidor reiniciado. Por favor, recargue la página"
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "Servidor en proceso de apagado. Por favor, cierre la ventana." msgstr "Servidor en proceso de apagado. Por favor, cierre la ventana."
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "Actualización realizada" msgstr "Actualización realizada"
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "búsqueda" msgstr "búsqueda"
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "Leer un libro" msgstr "Leer un libro"
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "¡Por favor completar todos los campos!" msgstr "¡Por favor completar todos los campos!"
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "registrarse" msgstr "registrarse"
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "Error desconocido. Por favor, inténtelo de nuevo mas tarde." msgstr "Error desconocido. Por favor, inténtelo de nuevo mas tarde."
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "Usuario o dirección de correo en uso." msgstr "Usuario o dirección de correo en uso."
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "Sesion iniciada como : '%(nickname)s'" msgstr "Sesion iniciada como : '%(nickname)s'"
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "Usuario o contraseña invalido" msgstr "Usuario o contraseña invalido"
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "Configurar primero los parametros SMTP por favor..." msgstr "Configurar primero los parametros SMTP por favor..."
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "Envio de Libro a %(kindlemail)s correctamente" msgstr "Envio de Libro a %(kindlemail)s correctamente"
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "Ha sucedido un error en el envio del Libro: %(res)s" msgstr "Ha sucedido un error en el envio del Libro: %(res)s"
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "Configurar primero la dirección de correo Kindle por favor..." msgstr "Configurar primero la dirección de correo Kindle por favor..."
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "El libro fue agregado a el estante: %(sname)s" msgstr "El libro fue agregado a el estante: %(sname)s"
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "El libro fue removido del estante: %(sname)s" msgstr "El libro fue removido del estante: %(sname)s"
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "Une étagère de ce nom '%(title)s' existe déjà." msgstr "Une étagère de ce nom '%(title)s' existe déjà."
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "Estante %(title)s creado" msgstr "Estante %(title)s creado"
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "Ha sucedido un error" msgstr "Ha sucedido un error"
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "crear un estante" msgstr "crear un estante"
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "Estante %(title)s cambiado" msgstr "Estante %(title)s cambiado"
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "Editar un estante" msgstr "Editar un estante"
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "Estante %(name)s fue borrado correctamente" msgstr "Estante %(name)s fue borrado correctamente"
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "Estante: '%(name)s'" msgstr "Estante: '%(name)s'"
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "Cambiar orden del estante: '%(name)s'" msgstr "Cambiar orden del estante: '%(name)s'"
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "Existe una cuenta vinculada a esta dirección de correo." msgstr "Existe una cuenta vinculada a esta dirección de correo."
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "Perfil de %(name)s" msgstr "Perfil de %(name)s"
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "Perfil actualizado" msgstr "Perfil actualizado"
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "Página de administración" msgstr "Página de administración"
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "Configuración de Calibre-web actualizada" msgstr "Configuración de Calibre-web actualizada"
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "Configuración básica" msgstr "Configuración básica"
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "Localicación de la BD inválida. Por favor, introduzca la ruta correcta." msgstr "Localicación de la BD inválida. Por favor, introduzca la ruta correcta."
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "Agregar un nuevo usuario" msgstr "Agregar un nuevo usuario"
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "Usuario '%(user)s' creado" msgstr "Usuario '%(user)s' creado"
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "" msgstr ""
"Se ha encontrado una cuenta vinculada a esta dirección de correo o nombre" "Se ha encontrado una cuenta vinculada a esta dirección de correo o nombre"
" de usuario." " de usuario."
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "Parámetros de correo actualizados" msgstr "Parámetros de correo actualizados"
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "Exito al realizar envio de prueba a %(kindlemail)s" msgstr "Exito al realizar envio de prueba a %(kindlemail)s"
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "Error al realizar envio de prueba a E-Mail: %(res)s" msgstr "Error al realizar envio de prueba a E-Mail: %(res)s"
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "Ajustes de correo electrónico actualizados" msgstr "Ajustes de correo electrónico actualizados"
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "Editar parametros de correo" msgstr "Editar parametros de correo"
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "Usuario '%(nick)s' borrado" msgstr "Usuario '%(nick)s' borrado"
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "Usuario '%(nick)s' actualizado" msgstr "Usuario '%(nick)s' actualizado"
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "Error inesperado." msgstr "Error inesperado."
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "Editar Usuario %(nick)s" msgstr "Editar Usuario %(nick)s"
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr ""
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "editar metainformación" msgstr "editar metainformación"
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "No se permite subir archivos con la extensión \"%s\" a este servidor" msgstr "No se permite subir archivos con la extensión \"%s\" a este servidor"
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "El archivo a subir debe tener una extensión" msgstr "El archivo a subir debe tener una extensión"
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "Fallo al crear la ruta %s (permiso negado)" msgstr "Fallo al crear la ruta %s (permiso negado)"
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "Fallo al almacenar el archivo %s (permiso negado)" msgstr "Fallo al almacenar el archivo %s (permiso negado)"
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "Fallo al borrar el archivo %s (permiso negado)" msgstr "Fallo al borrar el archivo %s (permiso negado)"
@ -525,10 +529,10 @@ msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "Regresar" msgstr "Regresar"
@ -540,104 +544,124 @@ msgstr "¿Seguro que quiere detener Calibre-web?"
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "Actualizando. Por favor, no recargue la página." msgstr "Actualizando. Por favor, no recargue la página."
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr ""
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "Titulo del Libro" msgstr "Titulo del Libro"
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "Autor" msgstr "Autor"
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "Descripcion" msgstr "Descripcion"
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "Etiqueta" msgstr "Etiqueta"
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "Series" msgstr "Series"
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "Id de la serie" msgstr "Id de la serie"
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "Puntaje" msgstr "Puntaje"
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "URL de la Cubierta (jpg)" msgstr "URL de la Cubierta (jpg)"
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "Lenguaje" msgstr "Lenguaje"
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "Si" msgstr "Si"
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "No" msgstr "No"
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "Ver libro tras la edicion" msgstr "Ver libro tras la edicion"
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "Obtener metainformación" msgstr "Obtener metainformación"
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "Enviar" msgstr "Enviar"
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr ""
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr ""
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr ""
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr ""
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "Palabra clave" msgstr "Palabra clave"
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr "Buscar palabras clave" msgstr "Buscar palabras clave"
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "¡Vamos!" msgstr "¡Vamos!"
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "Haga clic en la portada para cargar la metainformación en el formulario" msgstr "Haga clic en la portada para cargar la metainformación en el formulario"
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "Cargando..." msgstr "Cargando..."
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "¡Error en la búsqueda!" msgstr "¡Error en la búsqueda!"
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "¡Sin resultados! Por favor, pruebe otra palabra clave." msgstr "¡Sin resultados! Por favor, pruebe otra palabra clave."
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "Editor" msgstr "Editor"
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "Origen" msgstr "Origen"
@ -721,15 +745,19 @@ msgstr "Permitir subidas de archivos"
msgid "Allow Edit" msgid "Allow Edit"
msgstr "Permitir editar" msgstr "Permitir editar"
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Delete books"
msgstr ""
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "Permitir cambiar la clave" msgstr "Permitir cambiar la clave"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "Inicio de Sesion" msgstr "Inicio de Sesion"
@ -1104,11 +1132,11 @@ msgstr "Mostrar leídos y no leídos"
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "Mostrar libro aleatorios con vista detallada" msgstr "Mostrar libro aleatorios con vista detallada"
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "Borrar este usuario" msgstr "Borrar este usuario"
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "Descargas Recientes" msgstr "Descargas Recientes"

@ -20,7 +20,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Calibre-web\n" "Project-Id-Version: Calibre-web\n"
"Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: 2016-11-13 18:35+0100\n" "PO-Revision-Date: 2016-11-13 18:35+0100\n"
"Last-Translator: Nicolas Roudninski <nicoroud@gmail.com>\n" "Last-Translator: Nicolas Roudninski <nicoroud@gmail.com>\n"
"Language: fr\n" "Language: fr\n"
@ -31,7 +31,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "" msgstr ""
@ -60,327 +60,331 @@ msgstr "Impossible de trouver un format adapté à envoyer par courriel"
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "Impossible de convertir epub vers mobi" msgstr "Impossible de convertir epub vers mobi"
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "" msgstr ""
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "" msgstr ""
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "" msgstr ""
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "" msgstr ""
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "" msgstr ""
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "" msgstr ""
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "" msgstr ""
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "" msgstr ""
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "Derniers livres" msgstr "Derniers livres"
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "Livres populaires (les plus téléchargés)" msgstr "Livres populaires (les plus téléchargés)"
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "" msgstr ""
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "Livres au hasard" msgstr "Livres au hasard"
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "Liste des auteurs" msgstr "Liste des auteurs"
#: cps/web.py:1048 #: cps/web.py:1072
#, python-format #, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "" msgstr ""
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "" msgstr ""
"Erreur d'ouverture du livre numérique. Le fichier n'existe pas ou n'est " "Erreur d'ouverture du livre numérique. Le fichier n'existe pas ou n'est "
"pas accessible :" "pas accessible :"
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "Liste des séries" msgstr "Liste des séries"
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "Séries : %(serie)s" msgstr "Séries : %(serie)s"
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "Langues disponibles" msgstr "Langues disponibles"
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "Langue : %(name)s" msgstr "Langue : %(name)s"
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "Liste des catégories" msgstr "Liste des catégories"
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "Catégorie : %(name)s" msgstr "Catégorie : %(name)s"
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "Statistiques" msgstr "Statistiques"
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "" msgstr ""
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "" msgstr ""
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "" msgstr ""
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "" msgstr ""
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "Lire un livre" msgstr "Lire un livre"
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "SVP, complétez tous les champs !" msgstr "SVP, complétez tous les champs !"
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "S'enregistrer" msgstr "S'enregistrer"
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "Une erreur a eu lieu. Merci de réessayez plus tard." msgstr "Une erreur a eu lieu. Merci de réessayez plus tard."
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "Ce nom d'utilisateur ou cette adresse de courriel est déjà utilisée." msgstr "Ce nom d'utilisateur ou cette adresse de courriel est déjà utilisée."
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "Vous êtes maintenant connecté sous : '%(nickname)s'" msgstr "Vous êtes maintenant connecté sous : '%(nickname)s'"
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "Mauvais nom d'utilisateur ou mot de passe" msgstr "Mauvais nom d'utilisateur ou mot de passe"
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "Connexion" msgstr "Connexion"
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "Veillez configurer les paramètres smtp d'abord..." msgstr "Veillez configurer les paramètres smtp d'abord..."
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "Livres envoyés à %(kindlemail)s avec succès" msgstr "Livres envoyés à %(kindlemail)s avec succès"
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "Il y a eu une erreur en envoyant ce livre : %(res)s" msgstr "Il y a eu une erreur en envoyant ce livre : %(res)s"
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "Veuillez configurer votre adresse kindle d'abord..." msgstr "Veuillez configurer votre adresse kindle d'abord..."
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "Le livre a bien été ajouté à l'étagère : %(sname)s" msgstr "Le livre a bien été ajouté à l'étagère : %(sname)s"
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "Le livre a été supprimé de l'étagère %(sname)s" msgstr "Le livre a été supprimé de l'étagère %(sname)s"
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "Une étagère de ce nom '%(title)s' existe déjà." msgstr "Une étagère de ce nom '%(title)s' existe déjà."
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "Étagère %(title)s créée" msgstr "Étagère %(title)s créée"
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "Il y a eu une erreur" msgstr "Il y a eu une erreur"
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "Créer une étagère" msgstr "Créer une étagère"
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "" msgstr ""
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "" msgstr ""
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "L'étagère %(name)s a été supprimé avec succès" msgstr "L'étagère %(name)s a été supprimé avec succès"
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "Étagère : '%(name)s'" msgstr "Étagère : '%(name)s'"
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "" msgstr ""
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "Un compte avec cette adresse de courriel existe déjà." msgstr "Un compte avec cette adresse de courriel existe déjà."
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "Profil de %(name)s" msgstr "Profil de %(name)s"
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "Profil mis à jour" msgstr "Profil mis à jour"
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "" msgstr ""
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "" msgstr ""
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "" msgstr ""
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "" msgstr ""
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "Ajouter un nouvel utilisateur" msgstr "Ajouter un nouvel utilisateur"
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "Utilisateur '%(user)s' créé" msgstr "Utilisateur '%(user)s' créé"
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "Un compte avec cette adresse de courriel ou ce surnom existe déjà." msgstr "Un compte avec cette adresse de courriel ou ce surnom existe déjà."
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "Paramètres de courriel mis à jour" msgstr "Paramètres de courriel mis à jour"
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "" msgstr ""
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "" msgstr ""
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "" msgstr ""
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "Éditer les paramètres de courriel" msgstr "Éditer les paramètres de courriel"
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "Utilisateur '%(nick)s' supprimé" msgstr "Utilisateur '%(nick)s' supprimé"
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "Utilisateur '%(nick)s' mis à jour" msgstr "Utilisateur '%(nick)s' mis à jour"
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "Oups ! Une erreur inconnue a eu lieu." msgstr "Oups ! Une erreur inconnue a eu lieu."
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "Éditer l'utilisateur %(nick)s" msgstr "Éditer l'utilisateur %(nick)s"
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr ""
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "" msgstr ""
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "" msgstr ""
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "" msgstr ""
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "Impossible de créer le chemin %s (permission refusée)" msgstr "Impossible de créer le chemin %s (permission refusée)"
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "Impossible d'enregistrer le fichier %s (permission refusée)" msgstr "Impossible d'enregistrer le fichier %s (permission refusée)"
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "Impossible de supprimer le fichier %s (permission refusée)" msgstr "Impossible de supprimer le fichier %s (permission refusée)"
@ -531,10 +535,10 @@ msgid "Ok"
msgstr "" msgstr ""
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "Retour" msgstr "Retour"
@ -546,104 +550,124 @@ msgstr ""
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr ""
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "Titre du livre" msgstr "Titre du livre"
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "Auteur" msgstr "Auteur"
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "Description" msgstr "Description"
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "Étiquette" msgstr "Étiquette"
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "Séries" msgstr "Séries"
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "Id de série" msgstr "Id de série"
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "Évaluation" msgstr "Évaluation"
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "Adresse de la couverture (jpg)" msgstr "Adresse de la couverture (jpg)"
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "Langue" msgstr "Langue"
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "Oui" msgstr "Oui"
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "Non" msgstr "Non"
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "Voir le livre après l'édition" msgstr "Voir le livre après l'édition"
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "Soumettre" msgstr "Soumettre"
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr ""
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr ""
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr ""
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr ""
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr "" msgstr ""
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "Allez !" msgstr "Allez !"
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "" msgstr ""
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "" msgstr ""
@ -727,15 +751,19 @@ msgstr "Permettre les téléversements"
msgid "Allow Edit" msgid "Allow Edit"
msgstr "Permettre l'édition" msgstr "Permettre l'édition"
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Delete books"
msgstr ""
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "Permettre le changement de mot de passe" msgstr "Permettre le changement de mot de passe"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "Connexion" msgstr "Connexion"
@ -1108,11 +1136,11 @@ msgstr ""
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "" msgstr ""
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "Supprimer cet utilisateur" msgstr "Supprimer cet utilisateur"
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "Téléchargements récents" msgstr "Téléchargements récents"

@ -12,7 +12,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Calibre Web - polski (POT: 2017-04-11 22:51)\n" "Project-Id-Version: Calibre Web - polski (POT: 2017-04-11 22:51)\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: 2017-04-11 22:51+0200\n" "PO-Revision-Date: 2017-04-11 22:51+0200\n"
"Last-Translator: Radosław Kierznowski <radek.kierznowski@outlook.com>\n" "Last-Translator: Radosław Kierznowski <radek.kierznowski@outlook.com>\n"
"Language: pl\n" "Language: pl\n"
@ -24,7 +24,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "nie zainstalowane" msgstr "nie zainstalowane"
@ -55,325 +55,329 @@ msgstr ""
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "Nie można konwertować epub do mobi" msgstr "Nie można konwertować epub do mobi"
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "Gość" msgstr "Gość"
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "Żądanie o pakiet aktualizacji" msgstr "Żądanie o pakiet aktualizacji"
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "Pobieranie pakietu aktualizacji" msgstr "Pobieranie pakietu aktualizacji"
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "Rozpakowywanie pakietu aktualizacji" msgstr "Rozpakowywanie pakietu aktualizacji"
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "Pliki zostały zastąpione" msgstr "Pliki zostały zastąpione"
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "Połączenia z bazą danych zostały zakończone" msgstr "Połączenia z bazą danych zostały zakończone"
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "Serwer jest zatrzymany" msgstr "Serwer jest zatrzymany"
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "Aktualizacja zakończona, proszę nacisnąć OK i odświeżyć stronę" msgstr "Aktualizacja zakończona, proszę nacisnąć OK i odświeżyć stronę"
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "Ostatnie książki" msgstr "Ostatnie książki"
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "Najpopularniejsze książki (najczęściej pobierane)" msgstr "Najpopularniejsze książki (najczęściej pobierane)"
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "Najlepiej oceniane książki" msgstr "Najlepiej oceniane książki"
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "Losowe książki" msgstr "Losowe książki"
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "Lista autorów" msgstr "Lista autorów"
#: cps/web.py:1048 #: cps/web.py:1072
#, python-format #, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "Autor: %(name)s" msgstr "Autor: %(name)s"
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "Błąd otwierania e-booka. Plik nie istnieje lub plik nie jest dostępny:" msgstr "Błąd otwierania e-booka. Plik nie istnieje lub plik nie jest dostępny:"
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "Lista serii" msgstr "Lista serii"
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "Seria: %(serie)s" msgstr "Seria: %(serie)s"
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "Dostępne języki" msgstr "Dostępne języki"
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "Język: %(name)s" msgstr "Język: %(name)s"
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "Lista kategorii" msgstr "Lista kategorii"
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "Kategoria: %(name)s" msgstr "Kategoria: %(name)s"
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "Statystyki" msgstr "Statystyki"
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "Serwer uruchomiony ponownie, proszę odświeżyć stronę" msgstr "Serwer uruchomiony ponownie, proszę odświeżyć stronę"
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "Wykonano wyłączenie serwera, proszę zamknąć okno" msgstr "Wykonano wyłączenie serwera, proszę zamknąć okno"
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "Aktualizacja zakończona" msgstr "Aktualizacja zakończona"
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "szukaj" msgstr "szukaj"
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "Czytaj książkę" msgstr "Czytaj książkę"
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "Proszę wypełnić wszystkie pola!" msgstr "Proszę wypełnić wszystkie pola!"
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "rejestracja" msgstr "rejestracja"
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "Wystąpił nieznany błąd. Spróbuj ponownie później." msgstr "Wystąpił nieznany błąd. Spróbuj ponownie później."
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "Nazwa użytkownika lub adres e-mail jest już w użyciu." msgstr "Nazwa użytkownika lub adres e-mail jest już w użyciu."
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "Zalogowałeś się jako: '%(nickname)s'" msgstr "Zalogowałeś się jako: '%(nickname)s'"
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "Błędna nazwa użytkownika lub hasło" msgstr "Błędna nazwa użytkownika lub hasło"
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "logowanie" msgstr "logowanie"
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "Proszę najpierw skonfigurować ustawienia SMTP poczty e-mail..." msgstr "Proszę najpierw skonfigurować ustawienia SMTP poczty e-mail..."
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "Książka została pomyślnie wysłana do %(kindlemail)s" msgstr "Książka została pomyślnie wysłana do %(kindlemail)s"
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "Wystąpił błąd podczas wysyłania tej książki: %(res)s" msgstr "Wystąpił błąd podczas wysyłania tej książki: %(res)s"
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "Proszę najpierw skonfigurować adres e-mail swojego kindla..." msgstr "Proszę najpierw skonfigurować adres e-mail swojego kindla..."
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "Książka została dodana do półki: %(sname)s" msgstr "Książka została dodana do półki: %(sname)s"
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "Książka została usunięta z półki: %(sname)s" msgstr "Książka została usunięta z półki: %(sname)s"
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "Półka o nazwie '%(title)s' już istnieje." msgstr "Półka o nazwie '%(title)s' już istnieje."
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "Półka %(title)s została utworzona" msgstr "Półka %(title)s została utworzona"
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "Wystąpił błąd" msgstr "Wystąpił błąd"
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "utwórz półkę" msgstr "utwórz półkę"
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "Półka %(title)s została zmieniona" msgstr "Półka %(title)s została zmieniona"
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "Edytuj półkę" msgstr "Edytuj półkę"
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "pomyślnie usunięto półkę %(name)s" msgstr "pomyślnie usunięto półkę %(name)s"
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "Półka: '%(name)s'" msgstr "Półka: '%(name)s'"
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "Zmieniono kolejność półki: '%(name)s'" msgstr "Zmieniono kolejność półki: '%(name)s'"
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "Znaleziono istniejące konto dla tego adresu e-mail." msgstr "Znaleziono istniejące konto dla tego adresu e-mail."
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "Profil użytkownika %(name)s" msgstr "Profil użytkownika %(name)s"
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "Zaktualizowano profil" msgstr "Zaktualizowano profil"
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "Portal administracyjny" msgstr "Portal administracyjny"
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "Konfiguracja Calibre-web została zaktualizowana" msgstr "Konfiguracja Calibre-web została zaktualizowana"
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "Podstawowa konfiguracja" msgstr "Podstawowa konfiguracja"
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "Lokalizacja bazy danych jest nieprawidłowa, wpisz poprawną ścieżkę" msgstr "Lokalizacja bazy danych jest nieprawidłowa, wpisz poprawną ścieżkę"
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "Dodaj nowego użytkownika" msgstr "Dodaj nowego użytkownika"
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "Użytkownik '%(user)s' został utworzony" msgstr "Użytkownik '%(user)s' został utworzony"
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "Znaleziono istniejące konto dla tego adresu e-mail lub nazwy użytkownika." msgstr "Znaleziono istniejące konto dla tego adresu e-mail lub nazwy użytkownika."
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "Zaktualizowano ustawienia poczty e-mail" msgstr "Zaktualizowano ustawienia poczty e-mail"
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "Testowy e-mail został pomyślnie wysłany do %(kindlemail)s" msgstr "Testowy e-mail został pomyślnie wysłany do %(kindlemail)s"
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "Wystąpił błąd podczas wysyłania testowej wiadomości e-mail: %(res)s" msgstr "Wystąpił błąd podczas wysyłania testowej wiadomości e-mail: %(res)s"
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "Zaktualizowano ustawienia e-mail" msgstr "Zaktualizowano ustawienia e-mail"
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "Edytuj ustawienia poczty e-mail" msgstr "Edytuj ustawienia poczty e-mail"
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "Użytkownik '%(nick)s' został usunięty" msgstr "Użytkownik '%(nick)s' został usunięty"
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "Użytkownik '%(nick)s' został zaktualizowany" msgstr "Użytkownik '%(nick)s' został zaktualizowany"
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "Wystąpił nieznany błąd." msgstr "Wystąpił nieznany błąd."
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "Edytuj użytkownika %(nick)s" msgstr "Edytuj użytkownika %(nick)s"
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr ""
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "edytuj metadane" msgstr "edytuj metadane"
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "Rozszerzenie pliku \"%s\" nie jest dozwolone do przesłania na ten serwer" msgstr "Rozszerzenie pliku \"%s\" nie jest dozwolone do przesłania na ten serwer"
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "Plik do przesłania musi mieć rozszerzenie" msgstr "Plik do przesłania musi mieć rozszerzenie"
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "Nie udało się utworzyć łącza %s (Odmowa dostępu)." msgstr "Nie udało się utworzyć łącza %s (Odmowa dostępu)."
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "Nie można przechowywać pliku %s (Odmowa dostępu)." msgstr "Nie można przechowywać pliku %s (Odmowa dostępu)."
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "Nie udało się usunąć pliku %s (Odmowa dostępu)." msgstr "Nie udało się usunąć pliku %s (Odmowa dostępu)."
@ -524,10 +528,10 @@ msgid "Ok"
msgstr "OK" msgstr "OK"
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "Wróć" msgstr "Wróć"
@ -539,104 +543,124 @@ msgstr "Na pewno chcesz zatrzymać Calibre Web?"
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "Aktualizowanie, proszę nie odświeżać strony" msgstr "Aktualizowanie, proszę nie odświeżać strony"
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr ""
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "Tytuł książki" msgstr "Tytuł książki"
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "Autor" msgstr "Autor"
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "Opis" msgstr "Opis"
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "Tagi" msgstr "Tagi"
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "Seria" msgstr "Seria"
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "ID serii" msgstr "ID serii"
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "Ocena" msgstr "Ocena"
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "Adres URL okładki (jpg)" msgstr "Adres URL okładki (jpg)"
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "Język" msgstr "Język"
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "Tak" msgstr "Tak"
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "Nie" msgstr "Nie"
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "wyświetl książkę po edycji" msgstr "wyświetl książkę po edycji"
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "Uzyskaj metadane" msgstr "Uzyskaj metadane"
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "Wyślij" msgstr "Wyślij"
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr ""
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr ""
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr ""
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr ""
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "Słowo kluczowe" msgstr "Słowo kluczowe"
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr " Szukaj słowa kluczowego " msgstr " Szukaj słowa kluczowego "
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "Idź!" msgstr "Idź!"
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "Kliknij okładkę, aby załadować metadane do formularza" msgstr "Kliknij okładkę, aby załadować metadane do formularza"
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "Ładowanie..." msgstr "Ładowanie..."
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "Zamknij" msgstr "Zamknij"
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "Błąd wyszukiwania!" msgstr "Błąd wyszukiwania!"
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "Brak wyników! Spróbuj innego słowa kluczowego." msgstr "Brak wyników! Spróbuj innego słowa kluczowego."
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "Wydawca" msgstr "Wydawca"
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "Źródło" msgstr "Źródło"
@ -721,15 +745,19 @@ msgstr "Zezwalaj na wysyłanie"
msgid "Allow Edit" msgid "Allow Edit"
msgstr "Zezwalaj na edycję" msgstr "Zezwalaj na edycję"
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Delete books"
msgstr ""
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "Zezwalaj na zmianę hasła" msgstr "Zezwalaj na zmianę hasła"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "Zaloguj się" msgstr "Zaloguj się"
@ -1105,11 +1133,11 @@ msgstr "Pokaż przeczytane i nieprzeczytane"
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "Pokaz losowe książki w widoku szczegółowym" msgstr "Pokaz losowe książki w widoku szczegółowym"
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "Usuń tego użytkownika" msgstr "Usuń tego użytkownika"
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "Ostatnio pobierane" msgstr "Ostatnio pobierane"

@ -15,7 +15,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Calibre-web\n" "Project-Id-Version: Calibre-web\n"
"Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: 2017-01-06 17:00+0000\n" "PO-Revision-Date: 2017-01-06 17:00+0000\n"
"Last-Translator: dalin <dalin.lin@gmail.com>\n" "Last-Translator: dalin <dalin.lin@gmail.com>\n"
"Language: zh_Hans_CN\n" "Language: zh_Hans_CN\n"
@ -26,7 +26,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "未安装" msgstr "未安装"
@ -55,325 +55,329 @@ msgstr "无法找到适合邮件发送的格式"
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "无法转换epub到mobi" msgstr "无法转换epub到mobi"
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "游客" msgstr "游客"
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "正在请求更新包" msgstr "正在请求更新包"
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "正在下载更新包" msgstr "正在下载更新包"
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "正在解压更新包" msgstr "正在解压更新包"
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "文件已替换" msgstr "文件已替换"
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "数据库连接已关闭" msgstr "数据库连接已关闭"
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "服务器已停止" msgstr "服务器已停止"
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "更新完成,请按确定并刷新页面" msgstr "更新完成,请按确定并刷新页面"
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "最新书籍" msgstr "最新书籍"
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "热门书籍(最多下载)" msgstr "热门书籍(最多下载)"
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "最高评分书籍" msgstr "最高评分书籍"
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "随机书籍" msgstr "随机书籍"
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "作者列表" msgstr "作者列表"
#: cps/web.py:1048 #: cps/web.py:1072
#, python-forma, python-format #, python-forma, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "作者: %(name)s" msgstr "作者: %(name)s"
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "无法打开电子书。 文件不存在或者文件不可访问:" msgstr "无法打开电子书。 文件不存在或者文件不可访问:"
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "丛书列表" msgstr "丛书列表"
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "丛书: %(serie)s" msgstr "丛书: %(serie)s"
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "可用语言" msgstr "可用语言"
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "语言: %(name)s" msgstr "语言: %(name)s"
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "分类列表" msgstr "分类列表"
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "分类: %(name)s" msgstr "分类: %(name)s"
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "统计" msgstr "统计"
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "服务器已重启,请刷新页面" msgstr "服务器已重启,请刷新页面"
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "正在关闭服务器,请关闭窗口" msgstr "正在关闭服务器,请关闭窗口"
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "更新完成" msgstr "更新完成"
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "搜索" msgstr "搜索"
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "阅读一本书" msgstr "阅读一本书"
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "请填写所有字段" msgstr "请填写所有字段"
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "注册" msgstr "注册"
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "发生一个未知错误。请稍后再试。" msgstr "发生一个未知错误。请稍后再试。"
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "此用户名或邮箱已被使用。" msgstr "此用户名或邮箱已被使用。"
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "您现在已以'%(nickname)s'身份登录" msgstr "您现在已以'%(nickname)s'身份登录"
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "用户名或密码错误" msgstr "用户名或密码错误"
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "登录" msgstr "登录"
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "请先配置SMTP邮箱..." msgstr "请先配置SMTP邮箱..."
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "此书已被成功发给 %(kindlemail)s" msgstr "此书已被成功发给 %(kindlemail)s"
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "发送这本书的时候出现错误: %(res)s" msgstr "发送这本书的时候出现错误: %(res)s"
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "请先配置您的kindle电子邮箱地址..." msgstr "请先配置您的kindle电子邮箱地址..."
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "此书已被添加到书架: %(sname)s" msgstr "此书已被添加到书架: %(sname)s"
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "此书已从书架 %(sname)s 中删除" msgstr "此书已从书架 %(sname)s 中删除"
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "已存在书架 '%(title)s'。" msgstr "已存在书架 '%(title)s'。"
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "书架 %(title)s 已被创建" msgstr "书架 %(title)s 已被创建"
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "发生错误" msgstr "发生错误"
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "创建书架" msgstr "创建书架"
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "书架 %(title)s 已被修改" msgstr "书架 %(title)s 已被修改"
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "编辑书架" msgstr "编辑书架"
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "成功删除书架 %(name)s" msgstr "成功删除书架 %(name)s"
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "书架: '%(name)s'" msgstr "书架: '%(name)s'"
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "修改书架 '%(name)s' 顺序" msgstr "修改书架 '%(name)s' 顺序"
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "找到已使用此邮箱的账号。" msgstr "找到已使用此邮箱的账号。"
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "%(name)s 的资料" msgstr "%(name)s 的资料"
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "资料已更新" msgstr "资料已更新"
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "管理页" msgstr "管理页"
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "Calibre-web配置已更新" msgstr "Calibre-web配置已更新"
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "基本配置" msgstr "基本配置"
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "DB位置无效请输入正确路径" msgstr "DB位置无效请输入正确路径"
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "添加新用户" msgstr "添加新用户"
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "用户 '%(user)s' 已被创建" msgstr "用户 '%(user)s' 已被创建"
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "已存在使用此邮箱或昵称的账号。" msgstr "已存在使用此邮箱或昵称的账号。"
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "邮箱设置已更新" msgstr "邮箱设置已更新"
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "测试邮件已成功发送到 %(kindlemail)s" msgstr "测试邮件已成功发送到 %(kindlemail)s"
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "发送测试邮件时发生错误: %(res)s" msgstr "发送测试邮件时发生错误: %(res)s"
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "E-Mail 设置已更新" msgstr "E-Mail 设置已更新"
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "编辑邮箱设置" msgstr "编辑邮箱设置"
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "用户 '%(nick)s' 已被删除" msgstr "用户 '%(nick)s' 已被删除"
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "用户 '%(nick)s' 已被更新" msgstr "用户 '%(nick)s' 已被更新"
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "发生未知错误。" msgstr "发生未知错误。"
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "编辑用户 %(nick)s" msgstr "编辑用户 %(nick)s"
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr ""
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "编辑元数据" msgstr "编辑元数据"
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "不能上传后缀为 \"%s\" 的文件到此服务器" msgstr "不能上传后缀为 \"%s\" 的文件到此服务器"
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "要上传的文件必须有一个后缀" msgstr "要上传的文件必须有一个后缀"
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "创建路径 %s 失败(权限拒绝)。" msgstr "创建路径 %s 失败(权限拒绝)。"
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "存储文件 %s 失败(权限拒绝)。" msgstr "存储文件 %s 失败(权限拒绝)。"
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "删除文件 %s 失败(权限拒绝)。" msgstr "删除文件 %s 失败(权限拒绝)。"
@ -524,10 +528,10 @@ msgid "Ok"
msgstr "确定" msgstr "确定"
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "后退" msgstr "后退"
@ -539,104 +543,124 @@ msgstr "您确定要关闭 Calibre-web 吗?"
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "正在更新,请不要刷新页面" msgstr "正在更新,请不要刷新页面"
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr ""
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "书名" msgstr "书名"
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "作者" msgstr "作者"
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "简介" msgstr "简介"
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "标签" msgstr "标签"
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "丛书" msgstr "丛书"
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "丛书ID" msgstr "丛书ID"
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "评分" msgstr "评分"
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "封面URL (jpg)" msgstr "封面URL (jpg)"
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "语言" msgstr "语言"
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "确认" msgstr "确认"
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "编辑后查看书籍" msgstr "编辑后查看书籍"
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "获取元数据" msgstr "获取元数据"
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "提交" msgstr "提交"
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr ""
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr ""
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr ""
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr ""
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "关键字" msgstr "关键字"
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr "搜索关键字" msgstr "搜索关键字"
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "走起!" msgstr "走起!"
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "点击封面加载元数据到表单" msgstr "点击封面加载元数据到表单"
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "加载中..." msgstr "加载中..."
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "关闭" msgstr "关闭"
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "搜索错误" msgstr "搜索错误"
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "没有结果!请尝试别的关键字." msgstr "没有结果!请尝试别的关键字."
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "出版社" msgstr "出版社"
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "来源" msgstr "来源"
@ -720,15 +744,19 @@ msgstr "允许上传"
msgid "Allow Edit" msgid "Allow Edit"
msgstr "允许编辑" msgstr "允许编辑"
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Delete books"
msgstr ""
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "允许修改密码" msgstr "允许修改密码"
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "登录" msgstr "登录"
@ -1101,11 +1129,11 @@ msgstr "显示已读和未读"
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "在详情页显示随机书籍" msgstr "在详情页显示随机书籍"
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "删除此用户" msgstr "删除此用户"
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "最近下载" msgstr "最近下载"

@ -25,6 +25,8 @@ ROLE_EDIT = 8
ROLE_PASSWD = 16 ROLE_PASSWD = 16
ROLE_ANONYMOUS = 32 ROLE_ANONYMOUS = 32
ROLE_EDIT_SHELFS = 64 ROLE_EDIT_SHELFS = 64
ROLE_DELETE_BOOKS = 128
DETAIL_RANDOM = 1 DETAIL_RANDOM = 1
SIDEBAR_LANGUAGE = 2 SIDEBAR_LANGUAGE = 2
@ -90,6 +92,9 @@ class UserBase:
else: else:
return False return False
def role_delete_books(self):
return bool((self.role is not None)and(self.role & ROLE_DELETE_BOOKS == ROLE_DELETE_BOOKS))
@classmethod @classmethod
def is_active(self): def is_active(self):
return True return True
@ -336,6 +341,11 @@ class Config:
else: else:
return False return False
def role_delete_books(self):
return bool((self.config_default_role is not None) and
(self.config_default_role & ROLE_DELETE_BOOKS == ROLE_DELETE_BOOKS))
def get_Log_Level(self): def get_Log_Level(self):
ret_value="" ret_value=""
if self.config_log_level == logging.INFO: if self.config_log_level == logging.INFO:
@ -484,7 +494,7 @@ def create_anonymous_user():
def create_admin_user(): def create_admin_user():
user = User() user = User()
user.nickname = "admin" user.nickname = "admin"
user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_PASSWD user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_DELETE_BOOKS + ROLE_PASSWD
user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \ user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \
SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIDEBAR_BEST_RATED + SIDEBAR_READ_AND_UNREAD SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIDEBAR_BEST_RATED + SIDEBAR_READ_AND_UNREAD

@ -137,12 +137,14 @@ class Singleton:
@Singleton @Singleton
class Gauth: class Gauth:
def __init__(self): def __init__(self):
self.auth=GoogleAuth(settings_file='settings.yaml') self.auth = GoogleAuth(settings_file='settings.yaml')
@Singleton @Singleton
class Gdrive: class Gdrive:
def __init__(self): def __init__(self):
self.drive=gdriveutils.getDrive(Gauth.Instance().auth) self.drive = gdriveutils.getDrive(Gauth.Instance().auth)
class ReverseProxied(object): class ReverseProxied(object):
"""Wrap the application in this middleware and configure the """Wrap the application in this middleware and configure the
@ -223,7 +225,7 @@ lm.anonymous_user = ub.Anonymous
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
db.setup_db() db.setup_db()
if config.config_log_level == logging.DEBUG : if config.config_log_level == logging.DEBUG:
logging.getLogger("sqlalchemy.engine").addHandler(file_handler) logging.getLogger("sqlalchemy.engine").addHandler(file_handler)
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO) logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
logging.getLogger("sqlalchemy.pool").addHandler(file_handler) logging.getLogger("sqlalchemy.pool").addHandler(file_handler)
@ -235,6 +237,7 @@ if config.config_log_level == logging.DEBUG :
def is_gdrive_ready(): def is_gdrive_ready():
return os.path.exists('settings.yaml') and os.path.exists('gdrive_credentials') return os.path.exists('settings.yaml') and os.path.exists('gdrive_credentials')
@babel.localeselector @babel.localeselector
def get_locale(): def get_locale():
# if a user is logged in, use the locale from the user settings # if a user is logged in, use the locale from the user settings
@ -274,22 +277,26 @@ def load_user_from_header(header_val):
return user return user
return return
def check_auth(username, password): def check_auth(username, password):
user = ub.session.query(ub.User).filter(ub.User.nickname == username).first() user = ub.session.query(ub.User).filter(ub.User.nickname == username).first()
return bool(user and check_password_hash(user.password, password)) return bool(user and check_password_hash(user.password, password))
def authenticate(): def authenticate():
return Response( return Response(
'Could not verify your access level for that URL.\n' 'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401, 'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'}) {'WWW-Authenticate': 'Basic realm="Login Required"'})
def updateGdriveCalibreFromLocal(): def updateGdriveCalibreFromLocal():
gdriveutils.backupCalibreDbAndOptionalDownload(Gdrive.Instance().drive) gdriveutils.backupCalibreDbAndOptionalDownload(Gdrive.Instance().drive)
gdriveutils.copyToDrive(Gdrive.Instance().drive, config.config_calibre_dir, False, True) gdriveutils.copyToDrive(Gdrive.Instance().drive, config.config_calibre_dir, False, True)
for x in os.listdir(config.config_calibre_dir): for x in os.listdir(config.config_calibre_dir):
if os.path.isdir(os.path.join(config.config_calibre_dir,x)): if os.path.isdir(os.path.join(config.config_calibre_dir, x)):
shutil.rmtree(os.path.join(config.config_calibre_dir,x)) shutil.rmtree(os.path.join(config.config_calibre_dir, x))
def requires_basic_auth_if_no_ano(f): def requires_basic_auth_if_no_ano(f):
@wraps(f) @wraps(f)
@ -383,24 +390,27 @@ def mimetype_filter(val):
s = 'application/octet-stream' s = 'application/octet-stream'
return s return s
@app.template_filter('formatdate') @app.template_filter('formatdate')
def formatdate(val): def formatdate(val):
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', val) conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', val)
formatdate = datetime.datetime.strptime(conformed_timestamp[:15], "%Y%m%d %H%M%S") formatdate = datetime.datetime.strptime(conformed_timestamp[:15], "%Y%m%d %H%M%S")
return format_date(formatdate, format='medium',locale=get_locale()) return format_date(formatdate, format='medium', locale=get_locale())
@app.template_filter('strftime') @app.template_filter('strftime')
def timestamptodate(date, fmt=None): def timestamptodate(date, fmt=None):
date=datetime.datetime.fromtimestamp( date = datetime.datetime.fromtimestamp(
int(date)/1000 int(date)/1000
) )
native = date.replace(tzinfo=None) native = date.replace(tzinfo=None)
if fmt: if fmt:
time_format=fmt time_format = fmt
else: else:
time_format='%d %m %Y - %H:%S' time_format = '%d %m %Y - %H:%S'
return native.strftime(time_format) return native.strftime(time_format)
def admin_required(f): def admin_required(f):
""" """
Checks if current_user.role == 1 Checks if current_user.role == 1
@ -484,19 +494,27 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
del_elements = [] del_elements = []
for c_elements in db_book_object: for c_elements in db_book_object:
found = False found = False
if db_type == 'custom':
type_elements=c_elements.value
else:
type_elements=c_elements.name
for inp_element in input_elements: for inp_element in input_elements:
if inp_element == c_elements.name: if inp_element == type_elements:
found = True found = True
break break
# if the element was not found in the new list, add it to remove list # if the element was not found in the new list, add it to remove list
if not found: if not found:
del_elements.append(c_elements) del_elements.append(c_elements)
# 2. search for elements that need to be added # 2. search for elements that need to be added
add_elements = [] add_elements = []
for inp_element in input_elements: for inp_element in input_elements:
found = False found = False
for c_elements in db_book_object: for c_elements in db_book_object:
if inp_element == c_elements.name: if db_type == 'custom':
type_elements = c_elements.value
else:
type_elements = c_elements.name
if inp_element == type_elements:
found = True found = True
break break
if not found: if not found:
@ -511,6 +529,8 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
if len(add_elements) > 0: if len(add_elements) > 0:
if db_type == 'languages': if db_type == 'languages':
db_filter = db_object.lang_code db_filter = db_object.lang_code
elif db_type == 'custom':
db_filter = db_object.value
else: else:
db_filter = db_object.name db_filter = db_object.name
for add_element in add_elements: for add_element in add_elements:
@ -520,17 +540,17 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
if new_element is None: if new_element is None:
if db_type == 'author': if db_type == 'author':
new_element = db_object(add_element, add_element, "") new_element = db_object(add_element, add_element, "")
else: elif db_type == 'series':
if db_type == 'series': new_element = db_object(add_element, add_element)
new_element = db_object(add_element, add_element) elif db_type == 'custom':
else: # db_type should be tag, or languages new_element = db_object(value=add_element)
new_element = db_object(add_element) else: # db_type should be tag, or languages
new_element = db_object(add_element)
db_session.add(new_element) db_session.add(new_element)
new_element = db.session.query(db_object).filter(db_filter == add_element).first() new_element = db.session.query(db_object).filter(db_filter == add_element).first()
# add element to book # add element to book
db_book_object.append(new_element) db_book_object.append(new_element)
def render_title_template(*args, **kwargs): def render_title_template(*args, **kwargs):
return render_template(instance=config.config_calibre_web_title, *args, **kwargs) return render_template(instance=config.config_calibre_web_title, *args, **kwargs)
@ -642,6 +662,7 @@ def feed_best_rated():
response.headers["Content-Type"] = "application/xml" response.headers["Content-Type"] = "application/xml"
return response return response
@app.route("/opds/hot") @app.route("/opds/hot")
@requires_basic_auth_if_no_ano @requires_basic_auth_if_no_ano
def feed_hot(): def feed_hot():
@ -781,47 +802,49 @@ def partial(total_byte_len, part_size_limit):
s.append([p, last]) s.append([p, last])
return s return s
def do_gdrive_download(df, headers): def do_gdrive_download(df, headers):
total_size = int(df.metadata.get('fileSize')) total_size = int(df.metadata.get('fileSize'))
download_url = df.metadata.get('downloadUrl') download_url = df.metadata.get('downloadUrl')
s = partial(total_size, 1024 * 1024) # I'm downloading BIG files, so 100M chunk size is fine for me s = partial(total_size, 1024 * 1024) # I'm downloading BIG files, so 100M chunk size is fine for me
def stream(): def stream():
for byte in s: for byte in s:
headers = {"Range" : 'bytes=%s-%s' % (byte[0], byte[1])} headers = {"Range": 'bytes=%s-%s' % (byte[0], byte[1])}
resp, content = df.auth.Get_Http_Object().request(download_url, headers=headers) resp, content = df.auth.Get_Http_Object().request(download_url, headers=headers)
if resp.status == 206 : if resp.status == 206:
yield content yield content
else: else:
app.logger.info('An error occurred: %s' % resp) app.logger.info('An error occurred: %s' % resp)
return return
return Response(stream_with_context(stream()), headers=headers) return Response(stream_with_context(stream()), headers=headers)
@app.route("/opds/download/<book_id>/<book_format>/") @app.route("/opds/download/<book_id>/<book_format>/")
@requires_basic_auth_if_no_ano @requires_basic_auth_if_no_ano
@download_required @download_required
def get_opds_download_link(book_id, book_format): def get_opds_download_link(book_id, book_format):
startTime=time.time() startTime = time.time()
book_format = book_format.split(".")[0] book_format = book_format.split(".")[0]
book = db.session.query(db.Books).filter(db.Books.id == book_id).first() book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format.upper()).first() data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format.upper()).first()
app.logger.info (data.name) app.logger.info(data.name)
if current_user.is_authenticated: if current_user.is_authenticated:
helper.update_download(book_id, int(current_user.id)) helper.update_download(book_id, int(current_user.id))
file_name = book.title file_name = book.title
if len(book.authors) > 0: if len(book.authors) > 0:
file_name = book.authors[0].name + '_' + file_name file_name = book.authors[0].name + '_' + file_name
file_name = helper.get_valid_filename(file_name) file_name = helper.get_valid_filename(file_name)
headers = Headers () headers = Headers()
headers["Content-Disposition"] = "attachment; filename*=UTF-8''%s.%s" % (quote(file_name.encode('utf8')), book_format) headers["Content-Disposition"] = "attachment; filename*=UTF-8''%s.%s" % (quote(file_name.encode('utf8')), book_format)
app.logger.info (time.time()-startTime) app.logger.info(time.time()-startTime)
startTime=time.time() startTime = time.time()
if config.config_use_google_drive: if config.config_use_google_drive:
app.logger.info(time.time() - startTime) app.logger.info(time.time() - startTime)
df=gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, book.path, data.name + "." + book_format) df = gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, book.path, data.name + "." + book_format)
return do_gdrive_download(df, headers) return do_gdrive_download(df, headers)
else: else:
response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format)) response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format))
response.headers=headers response.headers = headers
return response return response
@ -856,11 +879,12 @@ def get_tags_json():
query = request.args.get('q') query = request.args.get('q')
# entries = db.session.execute("select name from tags where name like '%" + query + "%'") # entries = db.session.execute("select name from tags where name like '%" + query + "%'")
entries = db.session.query(db.Tags).filter(db.Tags.name.like("%" + query + "%")).all() entries = db.session.query(db.Tags).filter(db.Tags.name.like("%" + query + "%")).all()
#for x in entries: # for x in entries:
# alfa = dict(name=x.name) # alfa = dict(name=x.name)
json_dumps = json.dumps([dict(name=r.name) for r in entries]) json_dumps = json.dumps([dict(name=r.name) for r in entries])
return json_dumps return json_dumps
@app.route("/get_update_status", methods=['GET']) @app.route("/get_update_status", methods=['GET'])
@login_required_if_no_ano @login_required_if_no_ano
def get_update_status(): def get_update_status():
@ -880,7 +904,8 @@ def get_update_status():
status['status'] = False status['status'] = False
return json.dumps(status) return json.dumps(status)
@app.route("/get_updater_status", methods=['GET','POST'])
@app.route("/get_updater_status", methods=['GET', 'POST'])
@login_required @login_required
@admin_required @admin_required
def get_updater_status(): def get_updater_status():
@ -888,7 +913,7 @@ def get_updater_status():
if request.method == "POST": if request.method == "POST":
commit = request.form.to_dict() commit = request.form.to_dict()
if "start" in commit and commit['start'] == 'True': if "start" in commit and commit['start'] == 'True':
text={ text = {
"1": _(u'Requesting update package'), "1": _(u'Requesting update package'),
"2": _(u'Downloading update package'), "2": _(u'Downloading update package'),
"3": _(u'Unzipping update package'), "3": _(u'Unzipping update package'),
@ -1038,7 +1063,7 @@ def author_list():
@app.route("/author/<int:book_id>", defaults={'page': 1}) @app.route("/author/<int:book_id>", defaults={'page': 1})
@app.route("/author/<int:book_id>/<int:page>'") @app.route("/author/<int:book_id>/<int:page>'")
@login_required_if_no_ano @login_required_if_no_ano
def author(book_id,page): def author(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.authors.any(db.Authors.id == book_id), entries, random, pagination = fill_indexpage(page, db.Books, db.Books.authors.any(db.Authors.id == book_id),
db.Books.timestamp.desc()) db.Books.timestamp.desc())
name = db.session.query(db.Authors).filter(db.Authors.id == book_id).first().name name = db.session.query(db.Authors).filter(db.Authors.id == book_id).first().name
@ -1069,7 +1094,7 @@ def series_list():
def series(book_id, page): def series(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id), entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id),
db.Books.series_index) db.Books.series_index)
name=db.session.query(db.Series).filter(db.Series.id == book_id).first().name name = db.session.query(db.Series).filter(db.Series.id == book_id).first().name
if entries: if entries:
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, return render_title_template('index.html', random=random, pagination=pagination, entries=entries,
title=_(u"Series: %(serie)s", serie=name)) title=_(u"Series: %(serie)s", serie=name))
@ -1143,7 +1168,7 @@ def category(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id), entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
db.Books.timestamp.desc()) db.Books.timestamp.desc())
name=db.session.query(db.Tags).filter(db.Tags.id == book_id).first().name name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first().name
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Category: %(name)s", name=name)) title=_(u"Category: %(name)s", name=name))
@ -1154,17 +1179,18 @@ def toggle_read(book_id):
book = ub.session.query(ub.ReadBook).filter(ub.and_(ub.ReadBook.user_id == int(current_user.id), book = ub.session.query(ub.ReadBook).filter(ub.and_(ub.ReadBook.user_id == int(current_user.id),
ub.ReadBook.book_id == book_id)).first() ub.ReadBook.book_id == book_id)).first()
if book: if book:
book.is_read=not book.is_read book.is_read = not book.is_read
else: else:
readBook=ub.ReadBook() readBook = ub.ReadBook()
readBook.user_id=int(current_user.id) readBook.user_id = int(current_user.id)
readBook.book_id = book_id readBook.book_id = book_id
readBook.is_read=True readBook.is_read = True
book=readBook book = readBook
ub.session.merge(book) ub.session.merge(book)
ub.session.commit() ub.session.commit()
return "" return ""
@app.route("/book/<int:book_id>") @app.route("/book/<int:book_id>")
@login_required_if_no_ano @login_required_if_no_ano
def show_book(book_id): def show_book(book_id):
@ -1184,26 +1210,24 @@ def show_book(book_id):
tmpcc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all() tmpcc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
if config.config_columns_to_ignore: if config.config_columns_to_ignore:
cc=[] cc = []
for col in tmpcc: for col in tmpcc:
r= re.compile(config.config_columns_to_ignore) r = re.compile(config.config_columns_to_ignore)
if r.match(col.label): if r.match(col.label):
cc.append(col) cc.append(col)
else: else:
cc=tmpcc cc = tmpcc
book_in_shelfs = [] book_in_shelfs = []
shelfs = ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).all() shelfs = ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).all()
for entry in shelfs: for entry in shelfs:
book_in_shelfs.append(entry.shelf) book_in_shelfs.append(entry.shelf)
#return render_title_template('detail.html', entry=entries, cc=cc,
# title=entries.title, books_shelfs=book_in_shelfs)
if not current_user.is_anonymous(): if not current_user.is_anonymous():
matching_have_read_book=ub.session.query(ub.ReadBook).filter(ub.and_(ub.ReadBook.user_id == int(current_user.id), matching_have_read_book = ub.session.query(ub.ReadBook).filter(ub.and_(ub.ReadBook.user_id == int(current_user.id),
ub.ReadBook.book_id == book_id)).all() ub.ReadBook.book_id == book_id)).all()
have_read=len(matching_have_read_book) > 0 and matching_have_read_book[0].is_read have_read = len(matching_have_read_book) > 0 and matching_have_read_book[0].is_read
else: else:
have_read=None have_read = None
return render_title_template('detail.html', entry=entries, cc=cc, return render_title_template('detail.html', entry=entries, cc=cc,
title=entries.title, books_shelfs=book_in_shelfs, have_read=have_read) title=entries.title, books_shelfs=book_in_shelfs, have_read=have_read)
@ -1255,33 +1279,58 @@ def stats():
return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=versions, return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=versions,
categorycounter=categorys, seriecounter=series, title=_(u"Statistics")) categorycounter=categorys, seriecounter=series, title=_(u"Statistics"))
@app.route("/delete/<int:book_id>/")
@login_required
def delete_book(book_id):
if current_user.role_delete_books():
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
if book:
# check if only this book links to:
# author, language, series, tags,
modify_database_object([u''], book.authors, db.Authors, db.session, 'author')
modify_database_object([u''], book.tags, db.Tags, db.session, 'tags')
modify_database_object([u''], book.series, db.Series, db.session, 'series')
modify_database_object([u''], book.languages, db.Languages, db.session, 'languages')
modify_database_object([u''], book.publishers, db.Publishers, db.session, 'series')
# custom colums open
ub.session.query(db.Books).filter(db.Books.id == book_id).delete()
#return redirect(url_for('index'))
else:
app.logger.info('Book with id "'+book_id+'" could not be deleted')
# book not found
return redirect(url_for('index'))
@app.route("/gdrive/authenticate") @app.route("/gdrive/authenticate")
@login_required @login_required
@admin_required @admin_required
def authenticate_google_drive(): def authenticate_google_drive():
authUrl=Gauth.Instance().auth.GetAuthUrl() authUrl = Gauth.Instance().auth.GetAuthUrl()
return redirect(authUrl) return redirect(authUrl)
@app.route("/gdrive/callback") @app.route("/gdrive/callback")
def google_drive_callback(): def google_drive_callback():
auth_code = request.args.get('code') auth_code = request.args.get('code')
credentials = Gauth.Instance().auth.flow.step2_exchange(auth_code) credentials = Gauth.Instance().auth.flow.step2_exchange(auth_code)
with open('gdrive_credentials' ,'w') as f: with open('gdrive_credentials', 'w') as f:
f.write(credentials.to_json()) f.write(credentials.to_json())
return redirect(url_for('configuration')) return redirect(url_for('configuration'))
@app.route("/gdrive/watch/subscribe") @app.route("/gdrive/watch/subscribe")
@login_required @login_required
@admin_required @admin_required
def watch_gdrive(): def watch_gdrive():
if not config.config_google_drive_watch_changes_response: if not config.config_google_drive_watch_changes_response:
address = '%sgdrive/watch/callback' % config.config_google_drive_calibre_url_base address = '%sgdrive/watch/callback' % config.config_google_drive_calibre_url_base
notification_id=str(uuid4()) notification_id = str(uuid4())
result = gdriveutils.watchChange(Gdrive.Instance().drive, notification_id, result = gdriveutils.watchChange(Gdrive.Instance().drive, notification_id,
'web_hook', address, gdrive_watch_callback_token, current_milli_time() + 604800*1000) 'web_hook', address, gdrive_watch_callback_token, current_milli_time() + 604800*1000)
print (result) print (result)
settings = ub.session.query(ub.Settings).first() settings = ub.session.query(ub.Settings).first()
settings.config_google_drive_watch_changes_response=json.dumps(result) settings.config_google_drive_watch_changes_response = json.dumps(result)
ub.session.merge(settings) ub.session.merge(settings)
ub.session.commit() ub.session.commit()
settings = ub.session.query(ub.Settings).first() settings = ub.session.query(ub.Settings).first()
@ -1291,49 +1340,51 @@ def watch_gdrive():
return redirect(url_for('configuration')) return redirect(url_for('configuration'))
@app.route("/gdrive/watch/revoke") @app.route("/gdrive/watch/revoke")
@login_required @login_required
@admin_required @admin_required
def revoke_watch_gdrive(): def revoke_watch_gdrive():
last_watch_response=config.config_google_drive_watch_changes_response last_watch_response = config.config_google_drive_watch_changes_response
if last_watch_response: if last_watch_response:
try: try:
gdriveutils.stopChannel(Gdrive.Instance().drive, last_watch_response['id'], last_watch_response['resourceId']) gdriveutils.stopChannel(Gdrive.Instance().drive, last_watch_response['id'], last_watch_response['resourceId'])
except HttpError: except HttpError:
pass pass
settings = ub.session.query(ub.Settings).first() settings = ub.session.query(ub.Settings).first()
settings.config_google_drive_watch_changes_response=None settings.config_google_drive_watch_changes_response = None
ub.session.merge(settings) ub.session.merge(settings)
ub.session.commit() ub.session.commit()
config.loadSettings() config.loadSettings()
return redirect(url_for('configuration')) return redirect(url_for('configuration'))
@app.route("/gdrive/watch/callback", methods=['GET', 'POST']) @app.route("/gdrive/watch/callback", methods=['GET', 'POST'])
def on_received_watch_confirmation(): def on_received_watch_confirmation():
app.logger.info (request.headers) app.logger.info(request.headers)
if request.headers.get('X-Goog-Channel-Token') == gdrive_watch_callback_token \ if request.headers.get('X-Goog-Channel-Token') == gdrive_watch_callback_token \
and request.headers.get('X-Goog-Resource-State') == 'change' \ and request.headers.get('X-Goog-Resource-State') == 'change' \
and request.data: and request.data:
data=request.data data = request.data
def updateMetaData(): def updateMetaData():
app.logger.info ('Change received from gdrive') app.logger.info('Change received from gdrive')
app.logger.info (data) app.logger.info(data)
try: try:
j=json.loads(data) j = json.loads(data)
app.logger.info ('Getting change details') app.logger.info('Getting change details')
response=gdriveutils.getChangeById(Gdrive.Instance().drive, j['id']) response = gdriveutils.getChangeById(Gdrive.Instance().drive, j['id'])
app.logger.info (response) app.logger.info(response)
if response: if response:
dbpath = os.path.join(config.config_calibre_dir, "metadata.db") dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
if not response['deleted'] and response['file']['title'] == 'metadata.db' and response['file']['md5Checksum'] != md5(dbpath): if not response['deleted'] and response['file']['title'] == 'metadata.db' and response['file']['md5Checksum'] != md5(dbpath):
tmpDir=tempfile.gettempdir() tmpDir = tempfile.gettempdir()
app.logger.info ('Database file updated') app.logger.info('Database file updated')
copyfile (dbpath, os.path.join(tmpDir, "metadata.db_" + str(current_milli_time()))) copyfile(dbpath, os.path.join(tmpDir, "metadata.db_" + str(current_milli_time())))
app.logger.info ('Backing up existing and downloading updated metadata.db') app.logger.info('Backing up existing and downloading updated metadata.db')
gdriveutils.downloadFile(Gdrive.Instance().drive, None, "metadata.db", os.path.join(tmpDir, "tmp_metadata.db")) gdriveutils.downloadFile(Gdrive.Instance().drive, None, "metadata.db", os.path.join(tmpDir, "tmp_metadata.db"))
app.logger.info ('Setting up new DB') app.logger.info('Setting up new DB')
os.rename(os.path.join(tmpDir, "tmp_metadata.db"), dbpath) os.rename(os.path.join(tmpDir, "tmp_metadata.db"), dbpath)
db.setup_db() db.setup_db()
except Exception as e: except Exception as e:
@ -1373,6 +1424,7 @@ def shutdown():
return json.dumps({}) return json.dumps({})
abort(404) abort(404)
@app.route("/update") @app.route("/update")
@login_required @login_required
@admin_required @admin_required
@ -1473,20 +1525,21 @@ def advanced_search():
def get_cover_via_gdrive(cover_path): def get_cover_via_gdrive(cover_path):
df=gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, cover_path, 'cover.jpg') df = gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, cover_path, 'cover.jpg')
if not gdriveutils.session.query(gdriveutils.PermissionAdded).filter(gdriveutils.PermissionAdded.gdrive_id == df['id']).first(): if not gdriveutils.session.query(gdriveutils.PermissionAdded).filter(gdriveutils.PermissionAdded.gdrive_id == df['id']).first():
df.GetPermissions() df.GetPermissions()
df.InsertPermission({ df.InsertPermission({
'type': 'anyone', 'type': 'anyone',
'value': 'anyone', 'value': 'anyone',
'role': 'reader', 'role': 'reader',
'withLink' : True}) 'withLink': True})
permissionAdded=gdriveutils.PermissionAdded() permissionAdded = gdriveutils.PermissionAdded()
permissionAdded.gdrive_id=df['id'] permissionAdded.gdrive_id = df['id']
gdriveutils.session.add(permissionAdded) gdriveutils.session.add(permissionAdded)
gdriveutils.session.commit() gdriveutils.session.commit()
return df.metadata.get('webContentLink') return df.metadata.get('webContentLink')
@app.route("/cover/<path:cover_path>") @app.route("/cover/<path:cover_path>")
@login_required_if_no_ano @login_required_if_no_ano
def get_cover(cover_path): def get_cover(cover_path):
@ -1508,9 +1561,10 @@ def feed_get_cover(book_id):
else: else:
return send_from_directory(os.path.join(config.config_calibre_dir, book.path), "cover.jpg") return send_from_directory(os.path.join(config.config_calibre_dir, book.path), "cover.jpg")
def render_read_books(page, are_read, as_xml=False): def render_read_books(page, are_read, as_xml=False):
readBooks=ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id)).filter(ub.ReadBook.is_read == True).all() readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id)).filter(ub.ReadBook.is_read == True).all()
readBookIds=[x.book_id for x in readBooks] readBookIds = [x.book_id for x in readBooks]
if are_read: if are_read:
db_filter = db.Books.id.in_(readBookIds) db_filter = db.Books.id.in_(readBookIds)
else: else:
@ -1524,9 +1578,10 @@ def render_read_books(page, are_read, as_xml=False):
response.headers["Content-Type"] = "application/xml" response.headers["Content-Type"] = "application/xml"
return response return response
else: else:
name=u'Read Books' if are_read else u'Unread Books' name = u'Read Books' if are_read else u'Unread Books'
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(name, name=name)) title=_(name, name=name))
@app.route("/opds/readbooks/") @app.route("/opds/readbooks/")
@login_required_if_no_ano @login_required_if_no_ano
@ -1536,12 +1591,14 @@ def feed_read_books():
off = 0 off = 0
return render_read_books(int(off) / (int(config.config_books_per_page)) + 1, True, True) return render_read_books(int(off) / (int(config.config_books_per_page)) + 1, True, True)
@app.route("/readbooks/", defaults={'page': 1}) @app.route("/readbooks/", defaults={'page': 1})
@app.route("/readbooks/<int:page>'") @app.route("/readbooks/<int:page>'")
@login_required_if_no_ano @login_required_if_no_ano
def read_books(page): def read_books(page):
return render_read_books(page, True) return render_read_books(page, True)
@app.route("/opds/unreadbooks/") @app.route("/opds/unreadbooks/")
@login_required_if_no_ano @login_required_if_no_ano
def feed_unread_books(): def feed_unread_books():
@ -1550,12 +1607,14 @@ def feed_unread_books():
off = 0 off = 0
return render_read_books(int(off) / (int(config.config_books_per_page)) + 1, False, True) return render_read_books(int(off) / (int(config.config_books_per_page)) + 1, False, True)
@app.route("/unreadbooks/", defaults={'page': 1}) @app.route("/unreadbooks/", defaults={'page': 1})
@app.route("/unreadbooks/<int:page>'") @app.route("/unreadbooks/<int:page>'")
@login_required_if_no_ano @login_required_if_no_ano
def unread_books(page): def unread_books(page):
return render_read_books(page, False) return render_read_books(page, False)
@app.route("/read/<int:book_id>/<book_format>") @app.route("/read/<int:book_id>/<book_format>")
@login_required_if_no_ano @login_required_if_no_ano
def read_book(book_id, book_format): def read_book(book_id, book_format):
@ -1579,7 +1638,7 @@ def read_book(book_id, book_format):
try: try:
os.makedirs(newDir) os.makedirs(newDir)
except OSError as exception: except OSError as exception:
if not exception.errno == errno.EEXIST: if not exception.errno == errno.EEXIST:
raise raise
if fileName: if fileName:
fd = open(os.path.join(newDir, fileName), "wb") fd = open(os.path.join(newDir, fileName), "wb")
@ -1613,6 +1672,7 @@ def read_book(book_id, book_format):
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error") flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
return redirect(url_for("index")) return redirect(url_for("index"))
@app.route("/download/<int:book_id>/<book_format>") @app.route("/download/<int:book_id>/<book_format>")
@login_required_if_no_ano @login_required_if_no_ano
@download_required @download_required
@ -1628,28 +1688,30 @@ def get_download_link(book_id, book_format):
if len(book.authors) > 0: if len(book.authors) > 0:
file_name = book.authors[0].name + '_' + file_name file_name = book.authors[0].name + '_' + file_name
file_name = helper.get_valid_filename(file_name) file_name = helper.get_valid_filename(file_name)
headers = Headers () headers = Headers()
try: try:
headers["Content-Type"] = mimetypes.types_map['.' + book_format] headers["Content-Type"] = mimetypes.types_map['.' + book_format]
except KeyError: except KeyError:
headers["Content-Type"] = "application/octet-stream" headers["Content-Type"] = "application/octet-stream"
headers["Content-Disposition"] = "attachment; filename*=UTF-8''%s.%s" % (quote(file_name.encode('utf-8')), book_format) headers["Content-Disposition"] = "attachment; filename*=UTF-8''%s.%s" % (quote(file_name.encode('utf-8')), book_format)
if config.config_use_google_drive: if config.config_use_google_drive:
df=gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, book.path, '%s.%s' % (data.name, book_format)) df = gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, book.path, '%s.%s' % (data.name, book_format))
return do_gdrive_download(df, headers) return do_gdrive_download(df, headers)
else: else:
response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format)) response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format))
response.headers=headers response.headers = headers
return response return response
else: else:
abort(404) abort(404)
@app.route("/download/<int:book_id>/<book_format>/<anyname>") @app.route("/download/<int:book_id>/<book_format>/<anyname>")
@login_required_if_no_ano @login_required_if_no_ano
@download_required @download_required
def get_download_link_ext(book_id, book_format, anyname): def get_download_link_ext(book_id, book_format, anyname):
return get_download_link(book_id, book_format) return get_download_link(book_id, book_format)
@app.route('/register', methods=['GET', 'POST']) @app.route('/register', methods=['GET', 'POST'])
def register(): def register():
if not config.config_public_reg: if not config.config_public_reg:
@ -1745,7 +1807,7 @@ def add_to_shelf(shelf_id, book_id):
app.logger.info("Sorry you are not allowed to add a book to the the shelf: %s" % shelf.name) app.logger.info("Sorry you are not allowed to add a book to the the shelf: %s" % shelf.name)
return redirect(url_for('index')) return redirect(url_for('index'))
maxOrder = ub.session.query(func.max(ub.BookShelf.order)).filter(ub.BookShelf.shelf == shelf_id).first() maxOrder = ub.session.query(func.max(ub.BookShelf.order)).filter(ub.BookShelf.shelf == shelf_id).first()
book_in_shelf=ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id, book_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id,
ub.BookShelf.book_id == book_id).first() ub.BookShelf.book_id == book_id).first()
if book_in_shelf: if book_in_shelf:
app.logger.info("Book is already part of the shelf: %s" % shelf.name) app.logger.info("Book is already part of the shelf: %s" % shelf.name)
@ -1761,7 +1823,7 @@ def add_to_shelf(shelf_id, book_id):
flash(_(u"Book has been added to shelf: %(sname)s", sname=shelf.name), category="success") flash(_(u"Book has been added to shelf: %(sname)s", sname=shelf.name), category="success")
return redirect(request.environ["HTTP_REFERER"]) return redirect(request.environ["HTTP_REFERER"])
else: else:
app.logger.info("User is not allowed to edit public shelfs" ) app.logger.info("User is not allowed to edit public shelfs")
return redirect(url_for('index')) return redirect(url_for('index'))
@ -2016,30 +2078,30 @@ def configuration_helper(origin):
if content.config_calibre_dir != to_save["config_calibre_dir"]: if content.config_calibre_dir != to_save["config_calibre_dir"]:
content.config_calibre_dir = to_save["config_calibre_dir"] content.config_calibre_dir = to_save["config_calibre_dir"]
db_change = True db_change = True
##Google drive setup # Google drive setup
create_new_yaml=False create_new_yaml = False
if "config_google_drive_client_id" in to_save: if "config_google_drive_client_id" in to_save:
if content.config_google_drive_client_id != to_save["config_google_drive_client_id"]: if content.config_google_drive_client_id != to_save["config_google_drive_client_id"]:
content.config_google_drive_client_id = to_save["config_google_drive_client_id"] content.config_google_drive_client_id = to_save["config_google_drive_client_id"]
create_new_yaml=True create_new_yaml = True
if "config_google_drive_client_secret" in to_save: if "config_google_drive_client_secret" in to_save:
if content.config_google_drive_client_secret != to_save["config_google_drive_client_secret"]: if content.config_google_drive_client_secret != to_save["config_google_drive_client_secret"]:
content.config_google_drive_client_secret = to_save["config_google_drive_client_secret"] content.config_google_drive_client_secret = to_save["config_google_drive_client_secret"]
create_new_yaml=True create_new_yaml = True
if "config_google_drive_calibre_url_base" in to_save: if "config_google_drive_calibre_url_base" in to_save:
if content.config_google_drive_calibre_url_base != to_save["config_google_drive_calibre_url_base"]: if content.config_google_drive_calibre_url_base != to_save["config_google_drive_calibre_url_base"]:
content.config_google_drive_calibre_url_base = to_save["config_google_drive_calibre_url_base"] content.config_google_drive_calibre_url_base = to_save["config_google_drive_calibre_url_base"]
create_new_yaml=True create_new_yaml = True
if ("config_use_google_drive" in to_save and not content.config_use_google_drive) or ("config_use_google_drive" not in to_save and content.config_use_google_drive): if ("config_use_google_drive" in to_save and not content.config_use_google_drive) or ("config_use_google_drive" not in to_save and content.config_use_google_drive):
content.config_use_google_drive = "config_use_google_drive" in to_save content.config_use_google_drive = "config_use_google_drive" in to_save
db_change = True db_change = True
if not content.config_use_google_drive: if not content.config_use_google_drive:
create_new_yaml=False create_new_yaml = False
if create_new_yaml: if create_new_yaml:
with open('settings.yaml', 'w') as f: with open('settings.yaml', 'w') as f:
with open('gdrive_template.yaml' ,'r') as t: with open('gdrive_template.yaml', 'r') as t:
f.write(t.read() % {'client_id' : content.config_google_drive_client_id, 'client_secret' : content.config_google_drive_client_secret, f.write(t.read() % {'client_id': content.config_google_drive_client_id, 'client_secret': content.config_google_drive_client_secret,
"redirect_uri" : content.config_google_drive_calibre_url_base + 'gdrive/callback'}) "redirect_uri": content.config_google_drive_calibre_url_base + 'gdrive/callback'})
if "config_google_drive_folder" in to_save: if "config_google_drive_folder" in to_save:
if content.config_google_drive_folder != to_save["config_google_drive_folder"]: if content.config_google_drive_folder != to_save["config_google_drive_folder"]:
content.config_google_drive_folder = to_save["config_google_drive_folder"] content.config_google_drive_folder = to_save["config_google_drive_folder"]
@ -2082,6 +2144,8 @@ def configuration_helper(origin):
content.config_default_role = content.config_default_role + ub.ROLE_UPLOAD content.config_default_role = content.config_default_role + ub.ROLE_UPLOAD
if "edit_role" in to_save: if "edit_role" in to_save:
content.config_default_role = content.config_default_role + ub.ROLE_EDIT content.config_default_role = content.config_default_role + ub.ROLE_EDIT
if "delete_role" in to_save:
content.config_default_role = content.config_default_role + ub.ROLE_DELETE_BOOKS
if "passwd_role" in to_save: if "passwd_role" in to_save:
content.config_default_role = content.config_default_role + ub.ROLE_PASSWD content.config_default_role = content.config_default_role + ub.ROLE_PASSWD
if "passwd_role" in to_save: if "passwd_role" in to_save:
@ -2176,6 +2240,8 @@ def new_user():
if "upload_role" in to_save: if "upload_role" in to_save:
content.role = content.role + ub.ROLE_UPLOAD content.role = content.role + ub.ROLE_UPLOAD
if "edit_role" in to_save: if "edit_role" in to_save:
content.role = content.role + ub.ROLE_DELETE_BOOKS
if "delete_role" in to_save:
content.role = content.role + ub.ROLE_EDIT content.role = content.role + ub.ROLE_EDIT
if "passwd_role" in to_save: if "passwd_role" in to_save:
content.role = content.role + ub.ROLE_PASSWD content.role = content.role + ub.ROLE_PASSWD
@ -2190,7 +2256,7 @@ def new_user():
ub.session.rollback() ub.session.rollback()
flash(_(u"Found an existing account for this email address or nickname."), category="error") flash(_(u"Found an existing account for this email address or nickname."), category="error")
else: else:
content.role=config.config_default_role content.role = config.config_default_role
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations, return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
languages=languages, title=_(u"Add new user")) languages=languages, title=_(u"Add new user"))
@ -2279,6 +2345,11 @@ def edit_user(user_id):
elif "edit_role" not in to_save and content.role_edit(): elif "edit_role" not in to_save and content.role_edit():
content.role = content.role - ub.ROLE_EDIT content.role = content.role - ub.ROLE_EDIT
if "delete_role" in to_save and not content.role_delete_books():
content.role = content.role + ub.ROLE_DELETE_BOOKS
elif "delete_role" not in to_save and content.role_delete_books():
content.role = content.role - ub.ROLE_DELETE_BOOKS
if "passwd_role" in to_save and not content.role_passwd(): if "passwd_role" in to_save and not content.role_passwd():
content.role = content.role + ub.ROLE_PASSWD content.role = content.role + ub.ROLE_PASSWD
elif "passwd_role" not in to_save and content.role_passwd(): elif "passwd_role" not in to_save and content.role_passwd():
@ -2384,16 +2455,22 @@ def edit_book(book_id):
input_authors = to_save["author_name"].split('&') input_authors = to_save["author_name"].split('&')
input_authors = map(lambda it: it.strip(), input_authors) input_authors = map(lambda it: it.strip(), input_authors)
# we have all author names now # we have all author names now
author0_before_edit = book.authors[0].name if input_authors == ['']:
input_authors = [_(u'unknown')] # prevent empty Author
if book.authors:
author0_before_edit = book.authors[0].name
else:
author0_before_edit = db.Authors(_(u'unknown'),'',0)
modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author') modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author')
if author0_before_edit != book.authors[0].name: if book.authors:
edited_books_id.add(book.id) if author0_before_edit != book.authors[0].name:
book.author_sort=helper.get_sorted_author(input_authors[0]) edited_books_id.add(book.id)
book.author_sort = helper.get_sorted_author(input_authors[0])
if to_save["cover_url"] and os.path.splitext(to_save["cover_url"])[1].lower() == ".jpg": if to_save["cover_url"] and os.path.splitext(to_save["cover_url"])[1].lower() == ".jpg":
img = requests.get(to_save["cover_url"]) img = requests.get(to_save["cover_url"])
if config.config_use_google_drive: if config.config_use_google_drive:
tmpDir=tempfile.gettempdir() tmpDir = tempfile.gettempdir()
f = open(os.path.join(tmpDir, "uploaded_cover.jpg"), "wb") f = open(os.path.join(tmpDir, "uploaded_cover.jpg"), "wb")
f.write(img.content) f.write(img.content)
f.close() f.close()
@ -2402,7 +2479,7 @@ def edit_book(book_id):
f = open(os.path.join(config.config_calibre_dir, book.path, "cover.jpg"), "wb") f = open(os.path.join(config.config_calibre_dir, book.path, "cover.jpg"), "wb")
f.write(img.content) f.write(img.content)
f.close() f.close()
book.has_cover=1 book.has_cover = 1
if book.series_index != to_save["series_index"]: if book.series_index != to_save["series_index"]:
book.series_index = to_save["series_index"] book.series_index = to_save["series_index"]
@ -2510,7 +2587,8 @@ def edit_book(book_id):
else: else:
input_tags = to_save[cc_string].split(',') input_tags = to_save[cc_string].split(',')
input_tags = map(lambda it: it.strip(), input_tags) input_tags = map(lambda it: it.strip(), input_tags)
input_tags = [x for x in input_tags if x != ''] modify_database_object(input_tags, getattr(book, cc_string),db.cc_classes[c.id], db.session, 'custom')
'''input_tags = [x for x in input_tags if x != '']
# we have all author names now # we have all author names now
# 1. search for tags to remove # 1. search for tags to remove
del_tags = [] del_tags = []
@ -2552,7 +2630,7 @@ def edit_book(book_id):
new_tag = db.session.query(db.cc_classes[c.id]).filter( new_tag = db.session.query(db.cc_classes[c.id]).filter(
db.cc_classes[c.id].value == add_tag).first() db.cc_classes[c.id].value == add_tag).first()
# add tag to book # add tag to book
getattr(book, cc_string).append(new_tag) getattr(book, cc_string).append(new_tag)'''
db.session.commit() db.session.commit()
author_names = [] author_names = []
@ -2644,7 +2722,7 @@ def upload():
db_author = db.Authors(author, helper.get_sorted_author(author), "") db_author = db.Authors(author, helper.get_sorted_author(author), "")
db.session.add(db_author) db.session.add(db_author)
#add language actually one value in list # add language actually one value in list
input_language = meta.languages input_language = meta.languages
db_language = None db_language = None
if input_language != "": if input_language != "":
@ -2656,7 +2734,7 @@ def upload():
db_language = db.Languages(input_language) db_language = db.Languages(input_language)
db.session.add(db_language) db.session.add(db_language)
# combine path and normalize path from windows systems # combine path and normalize path from windows systems
path = os.path.join(author_dir, title_dir).replace('\\','/') path = os.path.join(author_dir, title_dir).replace('\\', '/')
db_book = db.Books(title, "", db_author.sort, datetime.datetime.now(), datetime.datetime(101, 1, 1), 1, db_book = db.Books(title, "", db_author.sort, datetime.datetime.now(), datetime.datetime(101, 1, 1), 1,
datetime.datetime.now(), path, has_cover, db_author, [], db_language) datetime.datetime.now(), path, has_cover, db_author, [], db_language)
db_book.authors.append(db_author) db_book.authors.append(db_author)
@ -2666,15 +2744,13 @@ def upload():
db_book.data.append(db_data) db_book.data.append(db_data)
db.session.add(db_book) db.session.add(db_book)
db.session.flush()# flush content get db_book.id avalible db.session.flush() # flush content get db_book.id avalible
#add comment # add comment
upload_comment = Markup(meta.description).unescape() upload_comment = Markup(meta.description).unescape()
db_comment = None
if upload_comment != "": if upload_comment != "":
db_comment = db.Comments(upload_comment, db_book.id) db.session.add(db.Comments(upload_comment, db_book.id))
db.session.add(db_comment)
db.session.commit() db.session.commit()
if db_language is not None: #display Full name instead of iso639.part3 if db_language is not None: # display Full name instead of iso639.part3
db_book.languages[0].language_name = _(meta.languages) db_book.languages[0].language_name = _(meta.languages)
author_names = [] author_names = []
for author in db_book.authors: for author in db_book.authors:
@ -2691,6 +2767,7 @@ def upload():
else: else:
return redirect(url_for("index")) return redirect(url_for("index"))
def start_gevent(): def start_gevent():
from gevent.wsgi import WSGIServer from gevent.wsgi import WSGIServer
global gevent_server global gevent_server

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-04-14 09:38+0200\n" "POT-Creation-Date: 2017-04-14 20:25+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n" "Generated-By: Babel 2.3.4\n"
#: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1235 #: cps/book_formats.py:113 cps/book_formats.py:117 cps/web.py:1258
msgid "not installed" msgid "not installed"
msgstr "" msgstr ""
@ -46,325 +46,329 @@ msgstr ""
msgid "Could not convert epub to mobi" msgid "Could not convert epub to mobi"
msgstr "" msgstr ""
#: cps/ub.py:471 #: cps/ub.py:481
msgid "Guest" msgid "Guest"
msgstr "" msgstr ""
#: cps/web.py:894 #: cps/web.py:917
msgid "Requesting update package" msgid "Requesting update package"
msgstr "" msgstr ""
#: cps/web.py:895 #: cps/web.py:918
msgid "Downloading update package" msgid "Downloading update package"
msgstr "" msgstr ""
#: cps/web.py:896 #: cps/web.py:919
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "" msgstr ""
#: cps/web.py:897 #: cps/web.py:920
msgid "Files are replaced" msgid "Files are replaced"
msgstr "" msgstr ""
#: cps/web.py:898 #: cps/web.py:921
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "" msgstr ""
#: cps/web.py:899 #: cps/web.py:922
msgid "Server is stopped" msgid "Server is stopped"
msgstr "" msgstr ""
#: cps/web.py:900 #: cps/web.py:923
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "" msgstr ""
#: cps/web.py:974 #: cps/web.py:997
msgid "Latest Books" msgid "Latest Books"
msgstr "" msgstr ""
#: cps/web.py:1005 #: cps/web.py:1028
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "" msgstr ""
#: cps/web.py:1015 #: cps/web.py:1038
msgid "Best rated books" msgid "Best rated books"
msgstr "" msgstr ""
#: cps/templates/index.xml:36 cps/web.py:1024 #: cps/templates/index.xml:36 cps/web.py:1047
msgid "Random Books" msgid "Random Books"
msgstr "" msgstr ""
#: cps/web.py:1037 #: cps/web.py:1060
msgid "Author list" msgid "Author list"
msgstr "" msgstr ""
#: cps/web.py:1048 #: cps/web.py:1072
#, python-format #, python-format
msgid "Author: %(name)s" msgid "Author: %(name)s"
msgstr "" msgstr ""
#: cps/web.py:1050 cps/web.py:1078 cps/web.py:1212 cps/web.py:1614 #: cps/web.py:1074 cps/web.py:1102 cps/web.py:1235 cps/web.py:1672
#: cps/web.py:2578 #: cps/web.py:2655
msgid "Error opening eBook. File does not exist or file is not accessible:" msgid "Error opening eBook. File does not exist or file is not accessible:"
msgstr "" msgstr ""
#: cps/templates/index.xml:71 cps/web.py:1064 #: cps/templates/index.xml:71 cps/web.py:1088
msgid "Series list" msgid "Series list"
msgstr "" msgstr ""
#: cps/web.py:1076 #: cps/web.py:1100
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "" msgstr ""
#: cps/web.py:1109 #: cps/web.py:1133
msgid "Available languages" msgid "Available languages"
msgstr "" msgstr ""
#: cps/web.py:1124 #: cps/web.py:1148
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "" msgstr ""
#: cps/templates/index.xml:64 cps/web.py:1137 #: cps/templates/index.xml:64 cps/web.py:1161
msgid "Category list" msgid "Category list"
msgstr "" msgstr ""
#: cps/web.py:1149 #: cps/web.py:1173
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "" msgstr ""
#: cps/web.py:1257 #: cps/web.py:1280
msgid "Statistics" msgid "Statistics"
msgstr "" msgstr ""
#: cps/web.py:1365 #: cps/web.py:1415
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "" msgstr ""
#: cps/web.py:1367 #: cps/web.py:1417
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "" msgstr ""
#: cps/web.py:1382 #: cps/web.py:1433
msgid "Update done" msgid "Update done"
msgstr "" msgstr ""
#: cps/web.py:1460 cps/web.py:1473 #: cps/web.py:1511 cps/web.py:1524
msgid "search" msgid "search"
msgstr "" msgstr ""
#: cps/web.py:1590 cps/web.py:1597 cps/web.py:1604 cps/web.py:1611 #: cps/web.py:1648 cps/web.py:1655 cps/web.py:1662 cps/web.py:1669
msgid "Read a Book" msgid "Read a Book"
msgstr "" msgstr ""
#: cps/web.py:1664 cps/web.py:2144 #: cps/web.py:1725 cps/web.py:2207
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "" msgstr ""
#: cps/web.py:1665 cps/web.py:1681 cps/web.py:1686 cps/web.py:1688 #: cps/web.py:1726 cps/web.py:1742 cps/web.py:1747 cps/web.py:1749
msgid "register" msgid "register"
msgstr "" msgstr ""
#: cps/web.py:1680 #: cps/web.py:1741
msgid "An unknown error occured. Please try again later." msgid "An unknown error occured. Please try again later."
msgstr "" msgstr ""
#: cps/web.py:1685 #: cps/web.py:1746
msgid "This username or email address is already in use." msgid "This username or email address is already in use."
msgstr "" msgstr ""
#: cps/web.py:1703 #: cps/web.py:1764
#, python-format #, python-format
msgid "you are now logged in as: '%(nickname)s'" msgid "you are now logged in as: '%(nickname)s'"
msgstr "" msgstr ""
#: cps/web.py:1708 #: cps/web.py:1769
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "" msgstr ""
#: cps/web.py:1710 #: cps/web.py:1771
msgid "login" msgid "login"
msgstr "" msgstr ""
#: cps/web.py:1727 #: cps/web.py:1788
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "" msgstr ""
#: cps/web.py:1731 #: cps/web.py:1792
#, python-format #, python-format
msgid "Book successfully send to %(kindlemail)s" msgid "Book successfully send to %(kindlemail)s"
msgstr "" msgstr ""
#: cps/web.py:1735 #: cps/web.py:1796
#, python-format #, python-format
msgid "There was an error sending this book: %(res)s" msgid "There was an error sending this book: %(res)s"
msgstr "" msgstr ""
#: cps/web.py:1737 cps/web.py:2226 #: cps/web.py:1798 cps/web.py:2291
msgid "Please configure your kindle email address first..." msgid "Please configure your kindle email address first..."
msgstr "" msgstr ""
#: cps/web.py:1762 #: cps/web.py:1823
#, python-format #, python-format
msgid "Book has been added to shelf: %(sname)s" msgid "Book has been added to shelf: %(sname)s"
msgstr "" msgstr ""
#: cps/web.py:1782 #: cps/web.py:1843
#, python-format #, python-format
msgid "Book has been removed from shelf: %(sname)s" msgid "Book has been removed from shelf: %(sname)s"
msgstr "" msgstr ""
#: cps/web.py:1800 cps/web.py:1824 #: cps/web.py:1861 cps/web.py:1885
#, python-format #, python-format
msgid "A shelf with the name '%(title)s' already exists." msgid "A shelf with the name '%(title)s' already exists."
msgstr "" msgstr ""
#: cps/web.py:1805 #: cps/web.py:1866
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "" msgstr ""
#: cps/web.py:1807 cps/web.py:1835 #: cps/web.py:1868 cps/web.py:1896
msgid "There was an error" msgid "There was an error"
msgstr "" msgstr ""
#: cps/web.py:1808 cps/web.py:1810 #: cps/web.py:1869 cps/web.py:1871
msgid "create a shelf" msgid "create a shelf"
msgstr "" msgstr ""
#: cps/web.py:1833 #: cps/web.py:1894
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "" msgstr ""
#: cps/web.py:1836 cps/web.py:1838 #: cps/web.py:1897 cps/web.py:1899
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "" msgstr ""
#: cps/web.py:1858 #: cps/web.py:1919
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "" msgstr ""
#: cps/web.py:1880 #: cps/web.py:1941
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "" msgstr ""
#: cps/web.py:1911 #: cps/web.py:1972
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "" msgstr ""
#: cps/web.py:1975 #: cps/web.py:2036
msgid "Found an existing account for this email address." msgid "Found an existing account for this email address."
msgstr "" msgstr ""
#: cps/web.py:1977 cps/web.py:1981 #: cps/web.py:2038 cps/web.py:2042
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "" msgstr ""
#: cps/web.py:1978 #: cps/web.py:2039
msgid "Profile updated" msgid "Profile updated"
msgstr "" msgstr ""
#: cps/web.py:1992 #: cps/web.py:2053
msgid "Admin page" msgid "Admin page"
msgstr "" msgstr ""
#: cps/web.py:2098 #: cps/web.py:2161
msgid "Calibre-web configuration updated" msgid "Calibre-web configuration updated"
msgstr "" msgstr ""
#: cps/web.py:2105 cps/web.py:2111 cps/web.py:2125 #: cps/web.py:2168 cps/web.py:2174 cps/web.py:2188
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "" msgstr ""
#: cps/web.py:2109 #: cps/web.py:2172
msgid "DB location is not valid, please enter correct path" msgid "DB location is not valid, please enter correct path"
msgstr "" msgstr ""
#: cps/templates/admin.html:34 cps/web.py:2146 cps/web.py:2196 #: cps/templates/admin.html:34 cps/web.py:2209 cps/web.py:2261
msgid "Add new user" msgid "Add new user"
msgstr "" msgstr ""
#: cps/web.py:2188 #: cps/web.py:2253
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "" msgstr ""
#: cps/web.py:2192 #: cps/web.py:2257
msgid "Found an existing account for this email address or nickname." msgid "Found an existing account for this email address or nickname."
msgstr "" msgstr ""
#: cps/web.py:2214 #: cps/web.py:2279
msgid "Mail settings updated" msgid "Mail settings updated"
msgstr "" msgstr ""
#: cps/web.py:2221 #: cps/web.py:2286
#, python-format #, python-format
msgid "Test E-Mail successfully send to %(kindlemail)s" msgid "Test E-Mail successfully send to %(kindlemail)s"
msgstr "" msgstr ""
#: cps/web.py:2224 #: cps/web.py:2289
#, python-format #, python-format
msgid "There was an error sending the Test E-Mail: %(res)s" msgid "There was an error sending the Test E-Mail: %(res)s"
msgstr "" msgstr ""
#: cps/web.py:2228 #: cps/web.py:2293
msgid "E-Mail settings updated" msgid "E-Mail settings updated"
msgstr "" msgstr ""
#: cps/web.py:2229 #: cps/web.py:2294
msgid "Edit mail settings" msgid "Edit mail settings"
msgstr "" msgstr ""
#: cps/web.py:2257 #: cps/web.py:2322
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "" msgstr ""
#: cps/web.py:2348 #: cps/web.py:2418
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "" msgstr ""
#: cps/web.py:2351 #: cps/web.py:2421
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "" msgstr ""
#: cps/web.py:2354 #: cps/web.py:2424
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "" msgstr ""
#: cps/web.py:2573 cps/web.py:2576 cps/web.py:2688 #: cps/web.py:2459 cps/web.py:2463
msgid "unknown"
msgstr ""
#: cps/web.py:2650 cps/web.py:2653 cps/web.py:2763
msgid "edit metadata" msgid "edit metadata"
msgstr "" msgstr ""
#: cps/web.py:2597 #: cps/web.py:2674
#, python-format #, python-format
msgid "File extension \"%s\" is not allowed to be uploaded to this server" msgid "File extension \"%s\" is not allowed to be uploaded to this server"
msgstr "" msgstr ""
#: cps/web.py:2603 #: cps/web.py:2680
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "" msgstr ""
#: cps/web.py:2620 #: cps/web.py:2697
#, python-format #, python-format
msgid "Failed to create path %s (Permission denied)." msgid "Failed to create path %s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:2625 #: cps/web.py:2702
#, python-format #, python-format
msgid "Failed to store file %s (Permission denied)." msgid "Failed to store file %s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:2630 #: cps/web.py:2707
#, python-format #, python-format
msgid "Failed to delete file %s (Permission denied)." msgid "Failed to delete file %s (Permission denied)."
msgstr "" msgstr ""
@ -515,10 +519,10 @@ msgid "Ok"
msgstr "" msgstr ""
#: cps/templates/admin.html:103 cps/templates/admin.html:117 #: cps/templates/admin.html:103 cps/templates/admin.html:117
#: cps/templates/book_edit.html:109 cps/templates/config_edit.html:123 #: cps/templates/book_edit.html:115 cps/templates/book_edit.html:134
#: cps/templates/email_edit.html:36 cps/templates/shelf.html:53 #: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
#: cps/templates/shelf_edit.html:19 cps/templates/shelf_order.html:12 #: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
#: cps/templates/user_edit.html:124 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@ -530,104 +534,124 @@ msgstr ""
msgid "Updating, please do not reload page" msgid "Updating, please do not reload page"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:16 cps/templates/search_form.html:6 #: cps/templates/book_edit.html:16
msgid "Delete Book"
msgstr ""
#: cps/templates/book_edit.html:22 cps/templates/search_form.html:6
msgid "Book Title" msgid "Book Title"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:20 cps/templates/book_edit.html:145 #: cps/templates/book_edit.html:26 cps/templates/book_edit.html:173
#: cps/templates/search_form.html:10 #: cps/templates/search_form.html:10
msgid "Author" msgid "Author"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:24 cps/templates/book_edit.html:147 #: cps/templates/book_edit.html:30 cps/templates/book_edit.html:175
msgid "Description" msgid "Description"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:28 cps/templates/search_form.html:17 #: cps/templates/book_edit.html:34 cps/templates/search_form.html:17
msgid "Tags" msgid "Tags"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:33 cps/templates/layout.html:142 #: cps/templates/book_edit.html:39 cps/templates/layout.html:142
#: cps/templates/search_form.html:37 #: cps/templates/search_form.html:37
msgid "Series" msgid "Series"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:37 #: cps/templates/book_edit.html:43
msgid "Series id" msgid "Series id"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:41 #: cps/templates/book_edit.html:47
msgid "Rating" msgid "Rating"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:45 #: cps/templates/book_edit.html:51
msgid "Cover URL (jpg)" msgid "Cover URL (jpg)"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:50 cps/templates/user_edit.html:27 #: cps/templates/book_edit.html:56 cps/templates/user_edit.html:27
msgid "Language" msgid "Language"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:61 #: cps/templates/book_edit.html:67
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:62 #: cps/templates/book_edit.html:68
msgid "No" msgid "No"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:104 #: cps/templates/book_edit.html:110
msgid "view book after edit" msgid "view book after edit"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:107 cps/templates/book_edit.html:118 #: cps/templates/book_edit.html:113 cps/templates/book_edit.html:146
msgid "Get metadata" msgid "Get metadata"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:108 cps/templates/config_edit.html:121 #: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
#: cps/templates/login.html:19 cps/templates/search_form.html:79 #: cps/templates/login.html:19 cps/templates/search_form.html:79
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:122 #: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
msgid "Submit" msgid "Submit"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:121 #: cps/templates/book_edit.html:125
msgid "Are really you sure?"
msgstr ""
#: cps/templates/book_edit.html:128
msgid "Book will be deleted from Calibre database"
msgstr ""
#: cps/templates/book_edit.html:129
msgid "and from hard disk"
msgstr ""
#: cps/templates/book_edit.html:133
msgid "Delete"
msgstr ""
#: cps/templates/book_edit.html:149
msgid "Keyword" msgid "Keyword"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:122 #: cps/templates/book_edit.html:150
msgid " Search keyword " msgid " Search keyword "
msgstr "" msgstr ""
#: cps/templates/book_edit.html:124 cps/templates/layout.html:60 #: cps/templates/book_edit.html:152 cps/templates/layout.html:60
msgid "Go!" msgid "Go!"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:125 #: cps/templates/book_edit.html:153
msgid "Click the cover to load metadata to the form" msgid "Click the cover to load metadata to the form"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:129 cps/templates/book_edit.html:142 #: cps/templates/book_edit.html:157 cps/templates/book_edit.html:170
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
#: cps/templates/book_edit.html:132 #: cps/templates/book_edit.html:160
msgid "Close" msgid "Close"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:143 #: cps/templates/book_edit.html:171
msgid "Search error!" msgid "Search error!"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:144 #: cps/templates/book_edit.html:172
msgid "No Result! Please try anonther keyword." msgid "No Result! Please try anonther keyword."
msgstr "" msgstr ""
#: cps/templates/book_edit.html:146 cps/templates/detail.html:76 #: cps/templates/book_edit.html:174 cps/templates/detail.html:76
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:148 #: cps/templates/book_edit.html:176
msgid "Source" msgid "Source"
msgstr "" msgstr ""
@ -711,15 +735,19 @@ msgstr ""
msgid "Allow Edit" msgid "Allow Edit"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:115 cps/templates/user_edit.html:105 #: cps/templates/config_edit.html:115 cps/templates/user_edit.html:104
msgid "Allow Changing Password" msgid "Allow Delete books"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109 #: cps/templates/config_edit.html:119 cps/templates/user_edit.html:109
msgid "Allow Changing Password"
msgstr ""
#: cps/templates/config_edit.html:123 cps/templates/user_edit.html:113
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
#: cps/templates/config_edit.html:126 cps/templates/layout.html:93 #: cps/templates/config_edit.html:130 cps/templates/layout.html:93
#: cps/templates/login.html:4 #: cps/templates/login.html:4
msgid "Login" msgid "Login"
msgstr "" msgstr ""
@ -1092,11 +1120,11 @@ msgstr ""
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "" msgstr ""
#: cps/templates/user_edit.html:116 #: cps/templates/user_edit.html:120
msgid "Delete this user" msgid "Delete this user"
msgstr "" msgstr ""
#: cps/templates/user_edit.html:131 #: cps/templates/user_edit.html:135
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "" msgstr ""

Loading…
Cancel
Save