From 808ac694efdc1eb6f3a4fb1888445c22dc66d6d5 Mon Sep 17 00:00:00 2001
From: Shizzz <kolmakov7@gmail.com>
Date: Fri, 24 Mar 2017 04:36:21 +0700
Subject: [PATCH] =?UTF-8?q?=D0=A7=D0=B8=D1=82=D0=B0=D0=BB=D0=BA=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Добавил возможность чтения книг в веб. Пока это является простым
преобразованием FB2, отображается сразу вся страница и книга не
сохраняется в кеш.
---
 opds_catalog/FB2_22_xhtml.xsl                 | 320 ++++++++
 opds_catalog/dl.py                            |  65 +-
 opds_catalog/locale/ru/LC_MESSAGES/django.mo  | Bin 4741 -> 4741 bytes
 opds_catalog/locale/ru/LC_MESSAGES/django.po  | 579 +++++++-------
 opds_catalog/urls.py                          |  18 +-
 sopds/locale/ru/LC_MESSAGES/django.mo         | Bin 5499 -> 5510 bytes
 sopds/locale/ru/LC_MESSAGES/django.po         | 319 ++++----
 .../locale/ru/LC_MESSAGES/django.mo           | Bin 5871 -> 5916 bytes
 .../locale/ru/LC_MESSAGES/django.po           | 729 +++++++++---------
 sopds_web_backend/templates/sopds_books.html  |   1 +
 10 files changed, 1210 insertions(+), 821 deletions(-)
 create mode 100644 opds_catalog/FB2_22_xhtml.xsl

diff --git a/opds_catalog/FB2_22_xhtml.xsl b/opds_catalog/FB2_22_xhtml.xsl
new file mode 100644
index 0000000..b1f49c7
--- /dev/null
+++ b/opds_catalog/FB2_22_xhtml.xsl
@@ -0,0 +1,320 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fb="http://www.gribuser.ru/xml/fictionbook/2.0">
+	<xsl:output method="xml" encoding="UTF-8"/>
+	<xsl:key name="note-link" match="fb:section" use="@id"/>
+	<xsl:template match="/*">
+		<html>
+			<head>
+				<xsl:if test="fb:description/fb:title-info/fb:lang = 'ru'">
+					<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
+				</xsl:if>
+				<title>
+					<xsl:value-of select="fb:description/fb:title-info/fb:book-title"/>
+				</title>
+				<style type="text/x-oeb1-css">
+					A { color : #0002CC }
+					A:HOVER { color : #BF0000 }
+					BODY { background-color : #FEFEFE; color : #000000; font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; text-align : justify }
+					H1{ font-size : 160%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Black;  background-color : #E7E7E7; margin-left : 0px;  page-break-before : always; }
+					H2{ font-size : 130%; font-style : normal; font-weight : bold; text-align : left; background-color : #EEEEEE;  border : 1px solid Gray;  page-break-before : always; }
+					H3{ font-size : 110%; font-style : normal; font-weight : bold; text-align : left;  background-color : #F1F1F1;  border : 1px solid Silver;}
+					H4{ font-size : 100%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Gray;  background-color : #F4F4F4;}
+					H5{ font-size : 100%; font-style : italic; font-weight : bold; text-align : left; border : 1px solid Gray;  background-color : #F4F4F4;}
+					H6{ font-size : 100%; font-style : italic; font-weight : normal; text-align : left; border : 1px solid Gray;  background-color : #F4F4F4;}
+					SMALL{ font-size : 80% }
+					BLOCKQUOTE{ margin-left :4em; margin-top:1em; margin-right:0.2em;}
+					HR{ color : Black }
+					UL{margin-left: 0}
+					.epigraph{width:50%; margin-left : 35%;}
+				</style>
+			</head>
+			<body>
+
+
+						<h4 align="center">
+        					<xsl:value-of select="fb:description/fb:title-info/fb:book-title"/>
+						</h4>
+
+<xsl:for-each select="fb:description/fb:title-info/fb:coverpage/fb:image">
+		<xsl:call-template name="image"/>
+		</xsl:for-each>
+
+				<xsl:for-each select="fb:description/fb:title-info/fb:annotation">
+
+					<div>
+						<xsl:call-template name="annotation"/>
+					</div>
+					<hr/>
+				</xsl:for-each>
+				<!-- BUILD TOC -->
+				<ul>
+					<xsl:apply-templates select="fb:body" mode="toc"/>
+				</ul>
+				<hr/>
+				<!-- BUILD BOOK -->
+				<xsl:for-each select="fb:body">
+					<xsl:if test="position()!=1">
+						<hr/>
+					</xsl:if>
+					<xsl:if test="@name">
+						<h4 align="center">
+							<xsl:value-of select="@name"/>
+						</h4>
+					</xsl:if>
+					<!-- <xsl:apply-templates /> -->
+					<xsl:apply-templates/>
+				</xsl:for-each>
+			</body>
+		</html>
+	</xsl:template>
+	<!-- author template -->
+	<xsl:template name="author">
+		<xsl:value-of select="fb:first-name"/>
+		<xsl:text disable-output-escaping="no">&#032;</xsl:text>
+		<xsl:value-of select="fb:middle-name"/>&#032;
+         <xsl:text disable-output-escaping="no">&#032;</xsl:text>
+		<xsl:value-of select="fb:last-name"/>
+		<br/>
+	</xsl:template>
+	<!-- secuence template -->
+	<xsl:template name="sequence">
+		<LI/>
+		<xsl:value-of select="@name"/>
+		<xsl:if test="@number">
+			<xsl:text disable-output-escaping="no">,&#032;#</xsl:text>
+			<xsl:value-of select="@number"/>
+		</xsl:if>
+		<xsl:if test="fb:sequence">
+			<ul>
+				<xsl:for-each select="fb:sequence">
+					<xsl:call-template name="sequence"/>
+				</xsl:for-each>
+			</ul>
+		</xsl:if>
+		<!--      <br/> -->
+	</xsl:template>
+	<!-- toc template -->
+	<xsl:template match="fb:section|fb:body" mode="toc">
+		<xsl:choose>
+			<xsl:when test="name()='body' and position()=1 and not(fb:title)">
+				<xsl:apply-templates select="fb:section" mode="toc"/>
+			</xsl:when>
+			<xsl:otherwise>
+				<li>
+					<a href="#TOC_{generate-id()}"><xsl:value-of select="normalize-space(fb:title/fb:p[1] | @name)"/></a>
+					<xsl:if test="fb:section">
+						<ul><xsl:apply-templates select="fb:section" mode="toc"/></ul>
+					</xsl:if>
+				</li>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+	<!-- description -->
+	<xsl:template match="fb:description">
+		<xsl:apply-templates/>
+	</xsl:template>
+	<!-- body -->
+	<xsl:template match="fb:body">
+		<div><xsl:apply-templates/></div>
+	</xsl:template>
+
+	<xsl:template match="fb:section">
+		<a name="TOC_{generate-id()}"></a>
+		<xsl:if test="@id">
+			<xsl:element name="a">
+				<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+			</xsl:element>
+		</xsl:if>
+		<xsl:apply-templates/>
+	</xsl:template>
+	
+	
+	<!-- section/title -->
+	<xsl:template match="fb:section/fb:title|fb:poem/fb:title">
+		<xsl:choose>
+			<xsl:when test="count(ancestor::node()) &lt; 9">
+				<xsl:element name="{concat('h',count(ancestor::node())-3)}">
+					<a name="TOC_{generate-id()}"></a>
+					<xsl:if test="@id">
+						<xsl:element name="a">
+							<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+						</xsl:element>
+					</xsl:if>
+					<xsl:apply-templates/>
+				</xsl:element>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:element name="h6">
+					<xsl:if test="@id">
+						<xsl:element name="a">
+							<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+						</xsl:element>
+					</xsl:if>
+					<xsl:apply-templates/>
+				</xsl:element>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+	<!-- section/title -->
+	<xsl:template match="fb:body/fb:title">
+		<h1><xsl:apply-templates mode="title"/></h1>
+	</xsl:template>
+
+	<xsl:template match="fb:title/fb:p">
+		<xsl:apply-templates/><xsl:text disable-output-escaping="no">&#032;</xsl:text><br/>
+	</xsl:template>
+	<!-- subtitle -->
+	<xsl:template match="fb:subtitle">
+		<xsl:if test="@id">
+			<xsl:element name="a">
+				<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+			</xsl:element>
+		</xsl:if>
+		<h5>
+			<xsl:apply-templates/>
+		</h5>
+	</xsl:template>
+	<!-- p -->
+	<xsl:template match="fb:p">
+		<div align="justify"><xsl:if test="@id">
+				<xsl:element name="a">
+					<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+				</xsl:element>
+			</xsl:if>	&#160;&#160;&#160;<xsl:apply-templates/></div>
+	</xsl:template>
+	<!-- strong -->
+	<xsl:template match="fb:strong">
+		<b><xsl:apply-templates/></b>
+	</xsl:template>
+	<!-- emphasis -->
+	<xsl:template match="fb:emphasis">
+		<i>	<xsl:apply-templates/></i>
+	</xsl:template>
+	<!-- style -->
+	<xsl:template match="fb:style">
+		<span class="{@name}"><xsl:apply-templates/></span>
+	</xsl:template>
+	<!-- empty-line -->
+	<xsl:template match="fb:empty-line">
+		<br/>
+	</xsl:template>
+	<!-- link -->
+	<xsl:template match="fb:a">
+		<xsl:element name="a">
+			<xsl:attribute name="href"><xsl:value-of select="@xlink:href"/></xsl:attribute>
+			<xsl:attribute name="title">
+				<xsl:choose>
+					<xsl:when test="starts-with(@xlink:href,'#')"><xsl:value-of select="key('note-link',substring-after(@xlink:href,'#'))/fb:p"/></xsl:when>
+					<xsl:otherwise><xsl:value-of select="key('note-link',@xlink:href)/fb:p"/></xsl:otherwise>
+				</xsl:choose>
+			</xsl:attribute>
+			<xsl:choose>
+				<xsl:when test="(@type) = 'note'">
+					<sup>
+						<xsl:apply-templates/>
+					</sup>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:apply-templates/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:element>
+	</xsl:template>
+	<!-- annotation -->
+	<xsl:template name="annotation">
+		<xsl:if test="@id">
+			<xsl:element name="a">
+				<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+			</xsl:element>
+		</xsl:if>
+		<h3>Annotation</h3>
+		<xsl:apply-templates/>
+	</xsl:template>
+	<!-- epigraph -->
+	<xsl:template match="fb:epigraph">
+		<blockquote class="epigraph">
+			<xsl:if test="@id">
+				<xsl:element name="a">
+					<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+				</xsl:element>
+			</xsl:if>
+			<xsl:apply-templates/>
+		</blockquote>
+	</xsl:template>
+	<!-- epigraph/text-author -->
+	<xsl:template match="fb:epigraph/fb:text-author">
+		<blockquote>
+			<i><xsl:apply-templates/></i>
+		</blockquote>
+	</xsl:template>
+	<!-- cite -->
+	<xsl:template match="fb:cite">
+		<blockquote>
+		<xsl:if test="@id">
+			<xsl:element name="a">
+				<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+			</xsl:element>
+		</xsl:if>
+		<xsl:apply-templates/>
+		</blockquote>
+	</xsl:template>
+	<!-- cite/text-author -->
+	<xsl:template match="fb:text-author">
+		<blockquote>
+		<i>	<xsl:apply-templates/></i></blockquote>
+	</xsl:template>
+	<!-- date -->
+	<xsl:template match="fb:date">
+		<xsl:choose>
+			<xsl:when test="not(@value)">
+				&#160;&#160;&#160;<xsl:apply-templates/>
+				<br/>
+			</xsl:when>
+			<xsl:otherwise>
+				&#160;&#160;&#160;<xsl:value-of select="@value"/>
+				<br/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+	<!-- poem -->
+	<xsl:template match="fb:poem">
+		<blockquote>
+			<xsl:if test="@id">
+				<xsl:element name="a">
+					<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+				</xsl:element>
+			</xsl:if>
+			<xsl:apply-templates/>
+		</blockquote>
+	</xsl:template>
+
+	<!-- stanza -->
+	<xsl:template match="fb:stanza">
+		<xsl:apply-templates/>
+		<br/>
+	</xsl:template>
+	<!-- v -->
+	<xsl:template match="fb:v">
+		<xsl:if test="@id">
+			<xsl:element name="a">
+				<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
+			</xsl:element>
+		</xsl:if>
+		<xsl:apply-templates/><br/>
+	</xsl:template>
+	<!-- image -->
+	<xsl:template match="fb:image" name="image">
+		<div align="center">
+			<img border="1">
+				<xsl:choose>
+					<xsl:when test="starts-with(@xlink:href,'#')">
+						<xsl:attribute name="src"><xsl:text>data:</xsl:text><xsl:variable name="href" select="substring-after(@xlink:href,'#')" /><set variable="href" expression="substring-after(@xlink:href,'#')"/><xsl:value-of select="//fb:binary[@id=$href]/@content-type" disable-output-escaping="yes" /><xsl:text>;base64,</xsl:text><!--<xsl:value-of select="substring-after(@xlink:href,'#')"/>--><xsl:value-of select="//fb:binary[@id=$href]"  disable-output-escaping="yes"/></xsl:attribute>
+
+					</xsl:when>
+					<xsl:otherwise>
+						<xsl:attribute name="src"><xsl:value-of select="@xlink:href"/></xsl:attribute>
+					</xsl:otherwise>
+				</xsl:choose>
+			</img>
+		</div>
+	</xsl:template>
+</xsl:stylesheet>
diff --git a/opds_catalog/dl.py b/opds_catalog/dl.py
index 8d6e013..5dbd3cc 100644
--- a/opds_catalog/dl.py
+++ b/opds_catalog/dl.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
-
 import os
 import codecs
 import base64
 import io
 import subprocess
+import lxml.etree as ET
 
 from django.http import HttpResponse, Http404
 
@@ -285,4 +285,67 @@ def ConvertFB2(request, book_id, convert_type):
     except: 
         pass
 
+    return response
+
+def ReadFB2(request, book_id):
+    """ Загрузка книги """
+    book = Book.objects.get(id=book_id)
+
+    if config.SOPDS_AUTH and request.user.is_authenticated():
+        bookshelf.objects.get_or_create(user=request.user, book=book)
+
+    full_path=os.path.join(config.SOPDS_ROOT_LIB,book.path)
+    
+    if book.cat_type==opdsdb.CAT_INP:
+        # Убираем из пути INPX файл
+        inpx_path, zip_name = os.path.split(full_path)
+        path, inpx_file = os.path.split(inpx_path)
+        full_path = os.path.join(path,zip_name)
+        
+    if config.SOPDS_TITLE_AS_FILENAME:
+        transname=utils.translit(book.title+'.'+book.format)
+    else:
+        transname=utils.translit(book.filename)
+        
+    transname = utils.to_ascii(transname)
+        
+    dlfilename=transname
+    content_type = mime_detector.fmt(book.format)
+
+    response = HttpResponse()
+    response["Content-Type"]='text/html; charset=utf-8'
+
+    z = None
+    fz = None
+    s = None
+    book_size = book.filesize
+    if book.cat_type==opdsdb.CAT_NORMAL:
+        file_path=os.path.join(full_path, book.filename)
+        book_size=os.path.getsize(file_path)
+        try:
+            fo=codecs.open(file_path, "rb")
+        except FileNotFoundError:
+            raise Http404
+        s=fo.read()
+    elif book.cat_type in [opdsdb.CAT_ZIP, opdsdb.CAT_INP]:
+        try:
+            fz=codecs.open(full_path, "rb")
+        except FileNotFoundError:
+            raise Http404
+        z = zipfile.ZipFile(fz, 'r', allowZip64=True)
+        book_size=z.getinfo(book.filename).file_size
+        fo= z.open(book.filename)
+
+    dom = ET.parse(fo)
+    xslt = ET.parse('%s/FB2_22_xhtml.xsl' % os.path.dirname(os.path.realpath(__file__)))
+    transform = ET.XSLT(xslt)
+    newdom = transform(dom)
+    book_content = ET.tostring(newdom, pretty_print=True)
+
+    response.write(book_content)
+
+    fo.close()
+    if z: z.close()
+    if fz: fz.close()
+
     return response
\ No newline at end of file
diff --git a/opds_catalog/locale/ru/LC_MESSAGES/django.mo b/opds_catalog/locale/ru/LC_MESSAGES/django.mo
index 91ec1887b138efa55f6ba2d98c3f453d4a934245..7481907f2fe16a7475d403d31989e454e1cc792e 100644
GIT binary patch
delta 42
xcmZowZB^Y+$;oA`Yh<ioWMpM(F}azumdhtGFTFG|J=IEK@_)|g&8b`p8~_XF4CMd-

delta 42
xcmZowZB^Y+$;oA;Yh<BdWN2k*G`X3xb}~0t6qiq8UV3R_da9Me<`gbP4gdg~3+ey>

diff --git a/opds_catalog/locale/ru/LC_MESSAGES/django.po b/opds_catalog/locale/ru/LC_MESSAGES/django.po
index 6b6d6c4..56341f5 100644
--- a/opds_catalog/locale/ru/LC_MESSAGES/django.po
+++ b/opds_catalog/locale/ru/LC_MESSAGES/django.po
@@ -1,290 +1,289 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-02-28 21:12+0300\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: \n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
-"10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%"
-"100>=11 && n%100<=14)? 2 : 3);\n"
-
-#: .\opds_catalog\feeds.py:129
-#, python-format
-msgid "All books by %(author)s"
-msgstr "Все книги автора %(author)s"
-
-#: .\opds_catalog\feeds.py:141
-msgid "Book doublicates"
-msgstr "Дубликаты книги"
-
-#: .\opds_catalog\feeds.py:162 .\opds_catalog\feeds.py:247
-#: .\opds_catalog\feeds.py:249 .\opds_catalog\tests\test_feeds.py:24
-msgid "By catalogs"
-msgstr "По каталогам"
-
-#: .\opds_catalog\feeds.py:163 .\opds_catalog\tests\test_feeds.py:25
-#, python-format
-msgid "Catalogs: %(catalogs)s, books: %(books)s."
-msgstr "Каталогов: %(catalogs)s, книг: %(books)s."
-
-#: .\opds_catalog\feeds.py:164
-msgid "By authors"
-msgstr "По авторам"
-
-#: .\opds_catalog\feeds.py:165 .\opds_catalog\tests\test_feeds.py:26
-#, python-format
-msgid "Authors: %(authors)s."
-msgstr "Авторов: %(authors)s."
-
-#: .\opds_catalog\feeds.py:166
-msgid "By titles"
-msgstr "По наименованиям"
-
-#: .\opds_catalog\feeds.py:167
-#, python-format
-msgid "Books: %(books)s."
-msgstr "Книг: %(books)s."
-
-#: .\opds_catalog\feeds.py:168
-msgid "By genres"
-msgstr "По жанрам"
-
-#: .\opds_catalog\feeds.py:169 .\opds_catalog\tests\test_feeds.py:27
-#, python-format
-msgid "Genres: %(genres)s."
-msgstr "Жанров: %(genres)s."
-
-#: .\opds_catalog\feeds.py:170
-msgid "By series"
-msgstr "По сериям"
-
-#: .\opds_catalog\feeds.py:171
-#, python-format
-msgid "Series: %(series)s."
-msgstr "Серий: %(series)s."
-
-#: .\opds_catalog\feeds.py:175
-#, python-format
-msgid "%(username)s Book shelf"
-msgstr "Книжная полка (%(username)s)"
-
-#: .\opds_catalog\feeds.py:176
-#, python-format
-msgid "%(username)s books readed: %(bookshelf)s."
-msgstr "Книг прочитано (%(username)s): %(bookshelf)s."
-
-#: .\opds_catalog\feeds.py:308 .\opds_catalog\feeds.py:554
-#, python-format
-msgid "<b>Authors: </b>%(authors)s<br/>"
-msgstr "<b>Авторов: </b>%(authors)s<br/>"
-
-#: .\opds_catalog\feeds.py:309 .\opds_catalog\feeds.py:555
-#, python-format
-msgid "<b>Genres: </b>%(genres)s<br/>"
-msgstr "<b>Жанров: </b>%(genres)s<br/>"
-
-#: .\opds_catalog\feeds.py:310 .\opds_catalog\feeds.py:556
-#, python-format
-msgid "<b>Series: </b>%(series)s<br/>"
-msgstr "<b>Серий: </b>%(series)s<br/>"
-
-#: .\opds_catalog\feeds.py:311 .\opds_catalog\feeds.py:557
-#, python-format
-msgid ""
-"<b>File: </b>%(filename)s<br/><b>File size: </b>%(filesize)s<br/><b>Changes "
-"date: </b>%(docdate)s<br/>"
-msgstr ""
-"<b>Файл: </b>%(filename)s<br/><b>Размер файла: </b>%(filesize)s<br/><b>Дата "
-"изменения: </b>%(docdate)s<br/>"
-
-#: .\opds_catalog\feeds.py:344 .\opds_catalog\tests\test_feeds.py:60
-msgid "Search by titles"
-msgstr "Поиск по наименованиям"
-
-#: .\opds_catalog\feeds.py:344
-msgid "Search books by title"
-msgstr "Поиск книг по наименованию"
-
-#: .\opds_catalog\feeds.py:345
-msgid "Search by authors"
-msgstr "Поиск авторов"
-
-#: .\opds_catalog\feeds.py:345
-msgid "Search authors by name"
-msgstr "Поиск авторов по имени"
-
-#: .\opds_catalog\feeds.py:346
-msgid "Search series"
-msgstr "Поиск серий"
-
-#: .\opds_catalog\feeds.py:378
-msgid "Books found"
-msgstr "Найдены книги"
-
-#: .\opds_catalog\feeds.py:378
-msgid "doubles hide"
-msgstr "дубликаты скрыты"
-
-#: .\opds_catalog\feeds.py:378
-msgid "doubles show"
-msgstr "дубликаты показаны"
-
-#: .\opds_catalog\feeds.py:558
-#, python-format
-msgid "<b>Doubles count: </b>%(doubles)s<br/>"
-msgstr "<b>Число дубликатов: </b>%(doubles)s<br/>"
-
-#: .\opds_catalog\feeds.py:572
-msgid "Series by authors select"
-msgstr "Выбор серий у автора"
-
-#: .\opds_catalog\feeds.py:593
-msgid "Books by series"
-msgstr "Книги по сериям"
-
-#: .\opds_catalog\feeds.py:593
-msgid "Books by author and series"
-msgstr "Книги по авторам и сериям"
-
-#: .\opds_catalog\feeds.py:594
-msgid "Books outside series"
-msgstr "Книги вне серий"
-
-#: .\opds_catalog\feeds.py:594
-msgid "Books by author outside series"
-msgstr "Книги автора вне серий"
-
-#: .\opds_catalog\feeds.py:595
-msgid "Books by alphabet"
-msgstr "Книги по алфавиту"
-
-#: .\opds_catalog\feeds.py:595
-msgid "Books by author alphabetical order"
-msgstr "Книги автора в алфавитном порядке"
-
-#: .\opds_catalog\feeds.py:626
-msgid "Authors found"
-msgstr "Найдены авторы"
-
-#: .\opds_catalog\feeds.py:679 .\opds_catalog\feeds.py:757
-#, python-format
-msgid "Books count: %s"
-msgstr "Всего: %s книг"
-
-#: .\opds_catalog\feeds.py:695
-msgid "Series found"
-msgstr "Найдены серии"
-
-#: .\opds_catalog\feeds.py:781
-msgid "Select language"
-msgstr "Выбор алфавита"
-
-#: .\opds_catalog\feeds.py:793 .\opds_catalog\tests\test_feeds.py:106
-#: .\opds_catalog\tests\test_feeds.py:119
-#: .\opds_catalog\tests\test_feeds.py:130
-msgid "Cyrillic"
-msgstr "Кириллица (РУС)"
-
-#: .\opds_catalog\feeds.py:794 .\opds_catalog\tests\test_feeds.py:107
-msgid "Latin"
-msgstr "Латинница (LAT)"
-
-#: .\opds_catalog\feeds.py:795 .\opds_catalog\tests\test_feeds.py:108
-msgid "Digits"
-msgstr "Цифры (0..9)"
-
-#: .\opds_catalog\feeds.py:796 .\opds_catalog\tests\test_feeds.py:109
-msgid "Other symbols"
-msgstr "Другие символы"
-
-#: .\opds_catalog\feeds.py:797 .\opds_catalog\tests\test_feeds.py:110
-msgid "Show all"
-msgstr "Показать все"
-
-#: .\opds_catalog\feeds.py:827
-msgid "Select books by substring"
-msgstr "Поиск книг по подстроке"
-
-#: .\opds_catalog\feeds.py:864 .\opds_catalog\feeds.py:1030
-#, python-format
-msgid "Found: %s books"
-msgstr "Найдено %s книг"
-
-#: .\opds_catalog\feeds.py:885
-msgid "Select authors by substring"
-msgstr "Поиск авторов по подстроке"
-
-#: .\opds_catalog\feeds.py:922
-#, python-format
-msgid "Found: %s authors"
-msgstr "Найдено %s авторов"
-
-#: .\opds_catalog\feeds.py:943
-msgid "Select series by substring"
-msgstr "Поиск серий по подстроке"
-
-#: .\opds_catalog\feeds.py:980
-#, python-format
-msgid "Found: %s series"
-msgstr "Найдено %s серий"
-
-#: .\opds_catalog\feeds.py:1001
-#, python-format
-msgid "Select genres (%s)"
-msgstr "Выбор жанра (%s)"
-
-#: .\opds_catalog\feeds.py:1001
-msgid "section"
-msgstr "секция"
-
-#: .\opds_catalog\feeds.py:1001
-msgid "subsection"
-msgstr "подсекция"
-
-#: .\opds_catalog\sopdscan.py:232
-msgid "Unknown author"
-msgstr "Неизвестный автор"
-
-#: .\opds_catalog\tests\test_feeds.py:78
-#, python-format
-msgid "All books by %(full_name)s"
-msgstr "Все книги автора %(full_name)s"
-
-#~ msgid "Book name:"
-#~ msgstr "Название:"
-
-#~ msgid "Authors:"
-#~ msgstr "Авторы:"
-
-#~ msgid "Genres:"
-#~ msgstr "Жанры:"
-
-#~ msgid "Series:"
-#~ msgstr "Серии:"
-
-#~ msgid "File:"
-#~ msgstr "Файл:"
-
-#~ msgid "File size:"
-#~ msgstr "Размер файла:"
-
-#~ msgid "Changes date:"
-#~ msgstr "Дата правки:"
-
-#~ msgid "Doubles count:"
-#~ msgstr "Число дубликатов:"
-
-#~ msgid "All books by %(last_name)s %(first_name)s"
-#~ msgstr "Все книги автора %(last_name)s %(first_name)s"
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-03-23 22:58+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
+"%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: opds_catalog/feeds.py:131
+#, python-format
+msgid "All books by %(author)s"
+msgstr "Все книги автора %(author)s"
+
+#: opds_catalog/feeds.py:143
+msgid "Book doublicates"
+msgstr "Дубликаты книги"
+
+#: opds_catalog/feeds.py:164 opds_catalog/feeds.py:249
+#: opds_catalog/feeds.py:251 opds_catalog/tests/test_feeds.py:24
+msgid "By catalogs"
+msgstr "По каталогам"
+
+#: opds_catalog/feeds.py:165 opds_catalog/tests/test_feeds.py:25
+#, python-format
+msgid "Catalogs: %(catalogs)s, books: %(books)s."
+msgstr "Каталогов: %(catalogs)s, книг: %(books)s."
+
+#: opds_catalog/feeds.py:166
+msgid "By authors"
+msgstr "По авторам"
+
+#: opds_catalog/feeds.py:167 opds_catalog/tests/test_feeds.py:26
+#, python-format
+msgid "Authors: %(authors)s."
+msgstr "Авторов: %(authors)s."
+
+#: opds_catalog/feeds.py:168
+msgid "By titles"
+msgstr "По наименованиям"
+
+#: opds_catalog/feeds.py:169
+#, python-format
+msgid "Books: %(books)s."
+msgstr "Книг: %(books)s."
+
+#: opds_catalog/feeds.py:170
+msgid "By genres"
+msgstr "По жанрам"
+
+#: opds_catalog/feeds.py:171 opds_catalog/tests/test_feeds.py:27
+#, python-format
+msgid "Genres: %(genres)s."
+msgstr "Жанров: %(genres)s."
+
+#: opds_catalog/feeds.py:172
+msgid "By series"
+msgstr "По сериям"
+
+#: opds_catalog/feeds.py:173
+#, python-format
+msgid "Series: %(series)s."
+msgstr "Серий: %(series)s."
+
+#: opds_catalog/feeds.py:177
+#, python-format
+msgid "%(username)s Book shelf"
+msgstr "Книжная полка (%(username)s)"
+
+#: opds_catalog/feeds.py:178
+#, python-format
+msgid "%(username)s books readed: %(bookshelf)s."
+msgstr "Книг прочитано (%(username)s): %(bookshelf)s."
+
+#: opds_catalog/feeds.py:318 opds_catalog/feeds.py:568
+#, python-format
+msgid "<b>Authors: </b>%(authors)s<br/>"
+msgstr "<b>Авторов: </b>%(authors)s<br/>"
+
+#: opds_catalog/feeds.py:319 opds_catalog/feeds.py:569
+#, python-format
+msgid "<b>Genres: </b>%(genres)s<br/>"
+msgstr "<b>Жанров: </b>%(genres)s<br/>"
+
+#: opds_catalog/feeds.py:320 opds_catalog/feeds.py:570
+#, python-format
+msgid "<b>Series: </b>%(series)s<br/>"
+msgstr "<b>Серий: </b>%(series)s<br/>"
+
+#: opds_catalog/feeds.py:321 opds_catalog/feeds.py:571
+#, python-format
+msgid ""
+"<b>File: </b>%(filename)s<br/><b>File size: </b>%(filesize)s<br/><b>Changes "
+"date: </b>%(docdate)s<br/>"
+msgstr ""
+"<b>Файл: </b>%(filename)s<br/><b>Размер файла: </b>%(filesize)s<br/><b>Дата "
+"изменения: </b>%(docdate)s<br/>"
+
+#: opds_catalog/feeds.py:354 opds_catalog/tests/test_feeds.py:60
+msgid "Search by titles"
+msgstr "Поиск по наименованиям"
+
+#: opds_catalog/feeds.py:354
+msgid "Search books by title"
+msgstr "Поиск книг по наименованию"
+
+#: opds_catalog/feeds.py:355
+msgid "Search by authors"
+msgstr "Поиск авторов"
+
+#: opds_catalog/feeds.py:355
+msgid "Search authors by name"
+msgstr "Поиск авторов по имени"
+
+#: opds_catalog/feeds.py:356
+msgid "Search series"
+msgstr "Поиск серий"
+
+#: opds_catalog/feeds.py:388
+msgid "Books found"
+msgstr "Найдены книги"
+
+#: opds_catalog/feeds.py:388
+msgid "doubles hide"
+msgstr "дубликаты скрыты"
+
+#: opds_catalog/feeds.py:388
+msgid "doubles show"
+msgstr "дубликаты показаны"
+
+#: opds_catalog/feeds.py:572
+#, python-format
+msgid "<b>Doubles count: </b>%(doubles)s<br/>"
+msgstr "<b>Число дубликатов: </b>%(doubles)s<br/>"
+
+#: opds_catalog/feeds.py:586
+msgid "Series by authors select"
+msgstr "Выбор серий у автора"
+
+#: opds_catalog/feeds.py:607
+msgid "Books by series"
+msgstr "Книги по сериям"
+
+#: opds_catalog/feeds.py:607
+msgid "Books by author and series"
+msgstr "Книги по авторам и сериям"
+
+#: opds_catalog/feeds.py:608
+msgid "Books outside series"
+msgstr "Книги вне серий"
+
+#: opds_catalog/feeds.py:608
+msgid "Books by author outside series"
+msgstr "Книги автора вне серий"
+
+#: opds_catalog/feeds.py:609
+msgid "Books by alphabet"
+msgstr "Книги по алфавиту"
+
+#: opds_catalog/feeds.py:609
+msgid "Books by author alphabetical order"
+msgstr "Книги автора в алфавитном порядке"
+
+#: opds_catalog/feeds.py:640
+msgid "Authors found"
+msgstr "Найдены авторы"
+
+#: opds_catalog/feeds.py:693 opds_catalog/feeds.py:771
+#, python-format
+msgid "Books count: %s"
+msgstr "Всего: %s книг"
+
+#: opds_catalog/feeds.py:709
+msgid "Series found"
+msgstr "Найдены серии"
+
+#: opds_catalog/feeds.py:795
+msgid "Select language"
+msgstr "Выбор алфавита"
+
+#: opds_catalog/feeds.py:807 opds_catalog/tests/test_feeds.py:106
+#: opds_catalog/tests/test_feeds.py:119 opds_catalog/tests/test_feeds.py:130
+msgid "Cyrillic"
+msgstr "Кириллица (РУС)"
+
+#: opds_catalog/feeds.py:808 opds_catalog/tests/test_feeds.py:107
+msgid "Latin"
+msgstr "Латинница (LAT)"
+
+#: opds_catalog/feeds.py:809 opds_catalog/tests/test_feeds.py:108
+msgid "Digits"
+msgstr "Цифры (0..9)"
+
+#: opds_catalog/feeds.py:810 opds_catalog/tests/test_feeds.py:109
+msgid "Other symbols"
+msgstr "Другие символы"
+
+#: opds_catalog/feeds.py:811 opds_catalog/tests/test_feeds.py:110
+msgid "Show all"
+msgstr "Показать все"
+
+#: opds_catalog/feeds.py:841
+msgid "Select books by substring"
+msgstr "Поиск книг по подстроке"
+
+#: opds_catalog/feeds.py:878 opds_catalog/feeds.py:1044
+#, python-format
+msgid "Found: %s books"
+msgstr "Найдено %s книг"
+
+#: opds_catalog/feeds.py:899
+msgid "Select authors by substring"
+msgstr "Поиск авторов по подстроке"
+
+#: opds_catalog/feeds.py:936
+#, python-format
+msgid "Found: %s authors"
+msgstr "Найдено %s авторов"
+
+#: opds_catalog/feeds.py:957
+msgid "Select series by substring"
+msgstr "Поиск серий по подстроке"
+
+#: opds_catalog/feeds.py:994
+#, python-format
+msgid "Found: %s series"
+msgstr "Найдено %s серий"
+
+#: opds_catalog/feeds.py:1015
+#, python-format
+msgid "Select genres (%s)"
+msgstr "Выбор жанра (%s)"
+
+#: opds_catalog/feeds.py:1015
+msgid "section"
+msgstr "секция"
+
+#: opds_catalog/feeds.py:1015
+msgid "subsection"
+msgstr "подсекция"
+
+#: opds_catalog/sopdscan.py:232
+msgid "Unknown author"
+msgstr "Неизвестный автор"
+
+#: opds_catalog/tests/test_feeds.py:78
+#, python-format
+msgid "All books by %(full_name)s"
+msgstr "Все книги автора %(full_name)s"
+
+#~ msgid "Book name:"
+#~ msgstr "Название:"
+
+#~ msgid "Authors:"
+#~ msgstr "Авторы:"
+
+#~ msgid "Genres:"
+#~ msgstr "Жанры:"
+
+#~ msgid "Series:"
+#~ msgstr "Серии:"
+
+#~ msgid "File:"
+#~ msgstr "Файл:"
+
+#~ msgid "File size:"
+#~ msgstr "Размер файла:"
+
+#~ msgid "Changes date:"
+#~ msgstr "Дата правки:"
+
+#~ msgid "Doubles count:"
+#~ msgstr "Число дубликатов:"
+
+#~ msgid "All books by %(last_name)s %(first_name)s"
+#~ msgstr "Все книги автора %(last_name)s %(first_name)s"
diff --git a/opds_catalog/urls.py b/opds_catalog/urls.py
index 7ab0496..4386283 100644
--- a/opds_catalog/urls.py
+++ b/opds_catalog/urls.py
@@ -6,38 +6,37 @@ urlpatterns = [
     url(r'^catalogs/$',feeds.CatalogsFeed(), name='catalogs'),
     url(r'^catalogs/(?P<cat_id>[0-9]+)/$',feeds.CatalogsFeed(), name='cat_tree'),
     url(r'^catalogs/(?P<cat_id>[0-9]+)/(?P<page>[0-9]+)/$',feeds.CatalogsFeed(), name='cat_page'),
-    
     url(r'^books/$',feeds.LangFeed(), name='lang_books'),
     url(r'^books/0/$',feeds.BooksFeed(), name='nolang_books'), 
     url(r'^books/(?P<lang_code>[0-9])/$',feeds.BooksFeed(), name='char_books'),
     url(r'^books/(?P<lang_code>[0-9])/(?P<chars>.+)/$',feeds.BooksFeed(), name='chars_books'),
-    
+
     url(r'^authors/$',feeds.LangFeed(), name='lang_authors'),
     url(r'^authors/0/$',feeds.AuthorsFeed(), name='nolang_authors'),
     url(r'^authors/(?P<lang_code>[0-9])/$',feeds.AuthorsFeed(), name='char_authors'),
     url(r'^authors/(?P<lang_code>[0-9])/(?P<chars>.+)/$',feeds.AuthorsFeed(), name='chars_authors'),
-    
+
     url(r'^series/$',feeds.LangFeed(), name='lang_series'),
     url(r'^series/0/$',feeds.SeriesFeed(), name='nolang_series'),
     url(r'^series/(?P<lang_code>[0-9])/$',feeds.SeriesFeed(), name='char_series'),
     url(r'^series/(?P<lang_code>[0-9])/(?P<chars>.+)/$',feeds.SeriesFeed(), name='chars_series'),
-         
+
     url(r'^genres/$',feeds.GenresFeed(), name='genres'),
     url(r'^genres/(?P<section>\d+)/$',feeds.GenresFeed(), name='genres'),
-    
+
     url(r'^search/$',feeds.OpenSearch, name='opensearch'),
-    #url(r'search/{searchTerms}/$',feeds.OpenSearch, name='search_template'),
-   
+        #url(r'search/{searchTerms}/$',feeds.OpenSearch, name='search_template'),
+
     url(r'^search/books/(?P<searchtype>[bmasgued])/(?P<searchterms>.+)/(?P<page>\d+)/$',feeds.SearchBooksFeed(), name='searchbooks'),
     url(r'^search/books/(?P<searchtype>[bmasgued])/(?P<searchterms>.+)/$',feeds.SearchBooksFeed(), name='searchbooks'),
     url(r'^search/books/(?P<searchtype>as)/(?P<searchterms>.+)/(?P<searchterms0>.+)/(?P<page>\d+)/$',feeds.SearchBooksFeed(), name='searchbooks'),
     url(r'^search/books/(?P<searchtype>as)/(?P<searchterms>.+)/(?P<searchterms0>.+)/$',feeds.SearchBooksFeed(), name='searchbooks'),
     url(r'^search/books/(?P<searchtype>as)/(?P<searchterms>.+)/$',feeds.SelectSeriesFeed(), name='searchbooks'),
     url(r'^search/books/u/0/$',feeds.SearchBooksFeed(), name='bookshelf'),
-                 
+
     url(r'^search/authors/(?P<searchtype>[bme])/(?P<searchterms>.+)/(?P<page>\d+)/$',feeds.SearchAuthorsFeed(), name='searchauthors'),
     url(r'^search/authors/(?P<searchtype>[bme])/(?P<searchterms>.+)/$',feeds.SearchAuthorsFeed(), name='searchauthors'),
-       
+
     url(r'^search/series/(?P<searchtype>[bmae])/(?P<searchterms>.+)/(?P<page>\d+)/$',feeds.SearchSeriesFeed(), name='searchseries'),
     url(r'^search/series/(?P<searchtype>[bmae])/(?P<searchterms>.+)/$',feeds.SearchSeriesFeed(), name='searchseries'),
 
@@ -47,6 +46,7 @@ urlpatterns = [
     url(r'^download/(?P<book_id>[0-9]+)/(?P<zip_flag>[0-1])/$',dl.Download, name='download'),
     url(r'^cover/(?P<book_id>[0-9]+)/$',dl.Cover, name='cover'),
     url(r'^thumb/(?P<book_id>[0-9]+)/$',dl.Thumbnail, name='thumb'),
+    url(r'^read/(?P<book_id>[0-9]+)/$',dl.ReadFB2, name='read'),
     url(r'^thumb/$',dl.Cover, name='covertmpl'),
         
     url(r'^$',feeds.MainFeed(), name='main'),
diff --git a/sopds/locale/ru/LC_MESSAGES/django.mo b/sopds/locale/ru/LC_MESSAGES/django.mo
index 07f4d7c6e50e8782babdb652a311b1bb1dcc008e..8e7e316ed1ad15fb6b534976b60de884a62f7ea2 100644
GIT binary patch
delta 299
zcmeyZ)uz2chOz!DBLl-vb_NC?1_p-roD2*}3=9l5Tnr4h3=9nOxfmF985kJuaxpMG
zVPIh3=4N2XU|?YQz|Fwm%fP@8$pg{1oQHv-fPsPG3l9T>CIbUQDldfY=Vf4MU|?X_
z$;-gt#K6E{#mB(l$iTo*%g4arz`($;pO2xQ!JdJEfq|ca!H|K0!GWKFL6m`kp@^S>
z!Hj`{p@W}+p%tW%pMhZ!0|SGr00YA+1_p)~0t^gUj0_Bu1tA9g6JlV9VPIge7iM5^
zVPIgGBh0{1&cML%P?&+i735G628JMzheQ|{+!+`cK8Y|ec!L}yx><_Jn2pO=*T`7G
d$jHjnVsbb~EtgMXUV3R_da9Me=F1!_cmO9HEoJ}!

delta 288
zcmZqE{;jn^hOzz?BLl-vb_NC?1_p*FoD2*}3=9m0Tnr4h3=9lYxEL6885kHYaWODF
zVPIfj;AUXRU|?W)%FV#w%fP_k#{<zfhlhcofPsPGB@Y9GCIbUQ6fcBs;bmZGU|?Wa
z$IHOr#K6Fy&&R;v$iTo*#K*wkz`($;g^!`0!JdJE;VT~lgCPS0gDF1)gD3+7LpnbL
zgBb$@LoGi8Ln}xjKLf)e1_lNz0S1Ou3=9l+1sE8z7#SEk1R(}}7GhwCVPIe|5oTa;
zVPIgGD9pf6&cMKMO_+hf735G628JMzheQ|{+!+`co{KOrc!L}yx><_Jn2pOw*T_P_
S$k58rXmU75?dJO&%Xt6|kST!x

diff --git a/sopds/locale/ru/LC_MESSAGES/django.po b/sopds/locale/ru/LC_MESSAGES/django.po
index e0a5b3c..2364674 100644
--- a/sopds/locale/ru/LC_MESSAGES/django.po
+++ b/sopds/locale/ru/LC_MESSAGES/django.po
@@ -1,159 +1,160 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-02-28 21:12+0300\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
-"10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%"
-"100>=11 && n%100<=14)? 2 : 3);\n"
-
-#: .\sopds\settings.py:165
-msgid "Select language"
-msgstr "Выбор языка"
-
-#: .\sopds\settings.py:166
-msgid "Absolute path to books collection directory"
-msgstr "Абсолютный путь к каталогу с файлами книг"
-
-#: .\sopds\settings.py:167
-msgid "List of managed book files extensions"
-msgstr "Список расширений файлов, для включения в коллекцию книг"
-
-#: .\sopds\settings.py:168
-msgid "Turn once scanning directly"
-msgstr "Запустить внеочередное однократное сканирование коллекции книг"
-
-#: .\sopds\settings.py:170
-msgid "Enable authentication"
-msgstr "Включить аутентификацию"
-
-#: .\sopds\settings.py:171
-msgid "Enable alphabet submenu"
-msgstr "Включить субменю выбора алфавита"
-
-#: .\sopds\settings.py:172
-msgid "This flag hides found doublicates"
-msgstr "Флаг прячет найденные дубликаты книг"
-
-#: .\sopds\settings.py:173
-msgid "This flag activate showing cover of books"
-msgstr "Флаг активирует показ обложек книг"
-
-#: .\sopds\settings.py:174
-msgid "Max subitems count in alphabet menuitem"
-msgstr "Максимальное число подэлементов в элементах алфавитных меню"
-
-#: .\sopds\settings.py:175
-msgid "Max items on page"
-msgstr "Максимальное число элементов на странице"
-
-#: .\sopds\settings.py:176
-msgid "Create downloaded filename from book title"
-msgstr "Имя загружаемого файла формировать из названия книги"
-
-#: .\sopds\settings.py:177
-msgid "Path to image file showing for book without embedded cover"
-msgstr "Путь к изображению, для показа в качестве обложки для книг без обложек"
-
-#: .\sopds\settings.py:180
-msgid "This flag activate SAX Parser for FB2 instead of lxml.xpath"
-msgstr ""
-"Флаг активирует стандартный FB2sax парсер (быстрее, парсит даже невалидные "
-"fb2). При отключенной опции будет использован FB2xpath парсер (немного "
-"медленне, требователен к валидности fb2, появился в версии 0.42)"
-
-#: .\sopds\settings.py:181
-msgid "This flag activate zip files scanning"
-msgstr "Флаг разрешает сканированеи содержимого ZIP файлов"
-
-#: .\sopds\settings.py:182
-msgid "Set codepage for filenames inside zipfile"
-msgstr "Codepage для имен файлов внутри ZIP"
-
-#: .\sopds\settings.py:183
-msgid ""
-"Enables read metadata from inpx-file (and stop scanning deeper from ipx-file "
-"place)"
-msgstr ""
-"Считываем метаданные книг з INPX-файлов (при этом не сканируем файлы и "
-"каталоги, расположенные на уровне или ниже найденого INPX)"
-
-#: .\sopds\settings.py:184
-msgid "Skip scanning INPX with unchanged size after previous scan"
-msgstr ""
-"Не сканируем INPX, если его размер не изменился с предидущего сканирования"
-
-#: .\sopds\settings.py:185
-msgid "Test avialability zip files listed in INPX before add in collection"
-msgstr ""
-"Проверяем наличие zip файлов, перечисленных в INPX перед добавлением их "
-"содержимого в коллекцию"
-
-#: .\sopds\settings.py:186
-msgid "Test avialability book files listed in INPX before add in collection"
-msgstr ""
-"Тестируем наличие книг, перечисленных в INPX перед добавлением их "
-"содержимого в коллекцию"
-
-#: .\sopds\settings.py:187
-msgid "Logical deleting unavialable files"
-msgstr "Логическое удаление отсутствующих файлов"
-
-#: .\sopds\settings.py:189
-msgid "sheduled minutes for sopds_scanner (cron syntax)"
-msgstr "минуты для планировщика sopds_Scanner (как в cron)"
-
-#: .\sopds\settings.py:190
-msgid "sheduled hours for sopds_scanner (cron syntax)"
-msgstr "часы для планировщика sopds_Scanner (как в cron)"
-
-#: .\sopds\settings.py:191
-msgid "sheduled day for sopds_scanner (cron syntax)"
-msgstr "дни для планировщика sopds_Scanner (как в cron)"
-
-#: .\sopds\settings.py:192
-msgid "sheduled day of weeks for sopds_scanner (cron syntax)"
-msgstr "дни недели для планировщика sopds_Scanner (как в cron)"
-
-#: .\sopds\settings.py:194
-msgid "Path to FB2-EPUB converter program"
-msgstr "Путь к конвертеру FB2-EPUB"
-
-#: .\sopds\settings.py:195
-msgid "Path to FB2-MOBI converter program"
-msgstr "Путь к конвертеру FB2-MOBI"
-
-#: .\sopds\settings.py:196
-msgid "Path to temporary files directory"
-msgstr "Путь к временному каталогу"
-
-#: .\sopds\settings.py:198
-msgid "Path to logfile for sopds_server process"
-msgstr "Путь к логфайлу для процесса sopds_server"
-
-#: .\sopds\settings.py:199
-msgid "Path to logfile for sopds_scanner process"
-msgstr "Путь к логфайлу для процесса sopds_scanner"
-
-#: .\sopds\settings.py:200
-msgid "Path to pidfile for sopds_server process"
-msgstr "Путь к pid-файлу для процесса sopds_server"
-
-#: .\sopds\settings.py:201
-msgid "Path to pidfile for sopds_scanner process"
-msgstr "Путь к pid-файлу для процесса sopds_scanner"
-
-#~ msgid "This flag activate extraction metadata from fb2 files"
-#~ msgstr "Флаг активирует извлеченеи метаданных из fb2-файлов"
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-03-23 22:58+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
+"%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: sopds/settings.py:165
+msgid "Select language"
+msgstr "Выбор языка"
+
+#: sopds/settings.py:166
+msgid "Absolute path to books collection directory"
+msgstr "Абсолютный путь к каталогу с файлами книг"
+
+#: sopds/settings.py:167
+msgid "List of managed book files extensions"
+msgstr "Список расширений файлов, для включения в коллекцию книг"
+
+#: sopds/settings.py:168
+msgid "Turn once scanning directly"
+msgstr "Запустить внеочередное однократное сканирование коллекции книг"
+
+#: sopds/settings.py:170
+msgid "Enable authentication"
+msgstr "Включить аутентификацию"
+
+#: sopds/settings.py:171
+msgid "Enable alphabet submenu"
+msgstr "Включить субменю выбора алфавита"
+
+#: sopds/settings.py:172
+msgid "This flag hides found doublicates"
+msgstr "Флаг прячет найденные дубликаты книг"
+
+#: sopds/settings.py:173
+msgid "This flag activate showing cover of books"
+msgstr "Флаг активирует показ обложек книг"
+
+#: sopds/settings.py:174
+msgid "Max subitems count in alphabet menuitem"
+msgstr "Максимальное число подэлементов в элементах алфавитных меню"
+
+#: sopds/settings.py:175
+msgid "Max items on page"
+msgstr "Максимальное число элементов на странице"
+
+#: sopds/settings.py:176
+msgid "Create downloaded filename from book title"
+msgstr "Имя загружаемого файла формировать из названия книги"
+
+#: sopds/settings.py:177
+msgid "Path to image file showing for book without embedded cover"
+msgstr "Путь к изображению, для показа в качестве обложки для книг без обложек"
+
+#: sopds/settings.py:180
+msgid "This flag activate SAX Parser for FB2 instead of lxml.xpath"
+msgstr ""
+"Флаг активирует стандартный FB2sax парсер (быстрее, парсит даже невалидные "
+"fb2). При отключенной опции будет использован FB2xpath парсер (немного "
+"медленне, требователен к валидности fb2, появился в версии 0.42)"
+
+#: sopds/settings.py:181
+msgid "This flag activate zip files scanning"
+msgstr "Флаг разрешает сканированеи содержимого ZIP файлов"
+
+#: sopds/settings.py:182
+msgid "Set codepage for filenames inside zipfile"
+msgstr "Codepage для имен файлов внутри ZIP"
+
+#: sopds/settings.py:183
+msgid ""
+"Enables read metadata from inpx-file (and stop scanning deeper from ipx-file "
+"place)"
+msgstr ""
+"Считываем метаданные книг з INPX-файлов (при этом не сканируем файлы и "
+"каталоги, расположенные на уровне или ниже найденого INPX)"
+
+#: sopds/settings.py:184
+msgid "Skip scanning INPX with unchanged size after previous scan"
+msgstr ""
+"Не сканируем INPX, если его размер не изменился с предидущего сканирования"
+
+#: sopds/settings.py:185
+msgid "Test avialability zip files listed in INPX before add in collection"
+msgstr ""
+"Проверяем наличие zip файлов, перечисленных в INPX перед добавлением их "
+"содержимого в коллекцию"
+
+#: sopds/settings.py:186
+msgid "Test avialability book files listed in INPX before add in collection"
+msgstr ""
+"Тестируем наличие книг, перечисленных в INPX перед добавлением их "
+"содержимого в коллекцию"
+
+#: sopds/settings.py:187
+msgid "Logical deleting unavialable files"
+msgstr "Логическое удаление отсутствующих файлов"
+
+#: sopds/settings.py:189
+msgid "sheduled minutes for sopds_scanner (cron syntax)"
+msgstr "минуты для планировщика sopds_Scanner (как в cron)"
+
+#: sopds/settings.py:190
+msgid "sheduled hours for sopds_scanner (cron syntax)"
+msgstr "часы для планировщика sopds_Scanner (как в cron)"
+
+#: sopds/settings.py:191
+msgid "sheduled day for sopds_scanner (cron syntax)"
+msgstr "дни для планировщика sopds_Scanner (как в cron)"
+
+#: sopds/settings.py:192
+msgid "sheduled day of weeks for sopds_scanner (cron syntax)"
+msgstr "дни недели для планировщика sopds_Scanner (как в cron)"
+
+#: sopds/settings.py:194
+msgid "Path to FB2-EPUB converter program"
+msgstr "Путь к конвертеру FB2-EPUB"
+
+#: sopds/settings.py:195
+msgid "Path to FB2-MOBI converter program"
+msgstr "Путь к конвертеру FB2-MOBI"
+
+#: sopds/settings.py:196
+msgid "Path to temporary files directory"
+msgstr "Путь к временному каталогу"
+
+#: sopds/settings.py:198
+msgid "Path to logfile for sopds_server process"
+msgstr "Путь к логфайлу для процесса sopds_server"
+
+#: sopds/settings.py:199
+msgid "Path to logfile for sopds_scanner process"
+msgstr "Путь к логфайлу для процесса sopds_scanner"
+
+#: sopds/settings.py:200
+msgid "Path to pidfile for sopds_server process"
+msgstr "Путь к pid-файлу для процесса sopds_server"
+
+#: sopds/settings.py:201
+msgid "Path to pidfile for sopds_scanner process"
+msgstr "Путь к pid-файлу для процесса sopds_scanner"
+
+#~ msgid "This flag activate extraction metadata from fb2 files"
+#~ msgstr "Флаг активирует извлеченеи метаданных из fb2-файлов"
diff --git a/sopds_web_backend/locale/ru/LC_MESSAGES/django.mo b/sopds_web_backend/locale/ru/LC_MESSAGES/django.mo
index 9667bc3f6ad7dd8debef2a3890b16b6b8bde82f0..ed8bd5f0dac8b8d9961dad8cf8c6f92abe39aa37 100644
GIT binary patch
delta 1408
zcmaE_J4dhno)F7a1_lNOX9fla83qOh6D9_RNCpN59~O`(1H%SZ1_m|;28NBS3=HfH
z3=BJ185lSi7#I$)GB9v5Ffg2CWnkcDU|_h+%D}+Nz`$@HD*lv}fgy~6f#E$=zZ)Aw
zpD!B&11|#uLl_$agD?X_Jwpl`L}LXT0|P$;14A7f1A{RG14ADh1A_ts1H&OUhyxz8
zF))ZSFfhDgV_*;fxs9EHL6CugL69Bd5M_1-20jJ`23;s^!_L6K#lXPe%?>d?j2&W5
z43wYD&cMLJP|v`S2^Gj=XJC+GU|=YLD(r`fPlNL3K>3TI7OrH6_-Hdb#7BGBAt7-J
zY%l}EH7I=>>W~Leb6&GUJn)H~fq}oCfq{XU10o>I0SN&W4v0%lptLmy#3CmS28Ieo
z1_o~q1_o&c28JV?3=HB73=9uAAwK-U$-p4Tz`*d2lYv2&fq_Am3!=`N3lg>AP`ZQ*
zqHZD=14F$b0|UbbE{Fw>xF9}x4dwsjf;fbU8xoY9+>kUN!p*?&m63r#1}ZMZ%fP?`
zvXB>|UyGN4L6U)i!GafJaS$&=e?C;aikE?58v_Hw6kdjUutsk_NC-smF))ZRFfe5D
zF)*kyFfcSg#h39hFlaF_Fl^^zV2Ea5V0gsGz~Ifmz+lG@iSsUg1_o^g28NmZ5T76A
zhxqU@KO{t%1Rx<HBmhZ6dIAg#5)2FsE&}zC#1kt3abY@?E)swkTnkm$Bf!95&cML1
zQ~(lEccJt%sQUL%^}hrlA;BpKp~VCt<|+$99Hs{q_kq%p^@0oxA`A=+X;6jLf{-9<
z6NDtj#ZY>mAOnL20|UcNs5&Mgh{3!<3=BdH3=9%N3=Aij7#OsL7#Iu~7#O~YFfeE`
zFfgc!LPFMGlz~Bwfq@}G6e8X(%D|w^z`#(yQ4|u?S49~ZR2Uc-enS;1h%qqaGB7Z>
zi!m_BGcYi06@wUbRSXiO&%_`h_YKMir9@CUARx}bzzE8oPz)+FKn_x3U|_IkU|>*(
zii14Oz`(%7;5a#xMW59cR0K_)%OdS*$pCSP69WT-HK;&>YH(nHqydm`jTj(h1Spl;
zFfcHH5-}(z=tI?lDAUP|tlF`93=n^V!omzB%)r241*O5I1p_3UL6Hke!k{7yBrVJU
zNy4C11>##UFfiyaK)eo0nV^!zZgVHA6BA2NYGTUfQ|uF&xr}v<j1`QGtV}H?r*hYF
m`6TA0mnNpCS}AOP$Q{Ybz5K$Ci%l0cTx`17v)Mv$J1YQ3t$^(S

delta 1377
zcmbQE_g=UDo)F7a1_lNOCk6%v83qOh9VP~bNCpN58y1i#1H%GV1_m|;28M;K3=HfH
z3=At+85lSi7#KFNGB9v5Ffi<7WnkcDU|=}R%D}+Nz`$@GDt?uffgy~6f#E(>zZn}u
zpDh~$11|#ugBu$IgD?X_Jwpf^L}LaU0|P$;14AAg1A{RG14A7f1A_ts1H&dZhyyOO
zF))ZSFfiO=V_*<qU|{&b#=s!Rz`(%B4snPuI|BnB0|SFBl-6NqVBlh4V6bL~nD538
zF~<kW4`ydzU}30dV2FeY#IZ9lNHH)lq(BwcL&e*m{2nNOGStGE><}L<W{3D_4Lc+x
zc7Y9MU^oVKz-g%dYwQq*-(`n*^c{#_&%nU&4=TXV0db)`lvd+_SfI<nz)-=+z+lF~
zz#z@Qz_6Z^fkB*sf#EbK#AlB=85rak7#Lo1GBC(8Ffed%LDZ>nL88<NO2>0S)YWh?
zFc>m0FwEv+V5kSh<ykI>53X@REPTQRamZUPNDzMEg2erQE(V5Ij0_Cy+z|0kJPZsx
z3=9l^c_8|^co`TZ85kHOcp(-W@j}%3L&c+b85p)PFff$xLiB0#G1P<O(t?kHL5zWc
z!IO`HL6w1lA%PDPRBe0=3|b5f4Ac1-7@`>%7!L6<FnBXCFv#&k;yR0;fkB&rfuWKg
z;`62a5FZ}qhXnB>en?1s;)kRiJ^=;>2?hoR6#+<^u@$I?xX@hyLI(*z4332=%n@K<
zFlS(3Xcd5j%w8yc466P-RQ)Xhh>u=E>2FYZW<iL<_yi&HI)V%gA`A=+mVyxb{OScE
zK@}+oNql8cdZHi$g9ZZw!y2f<t5EuZAOnLC0|UcrK?a5sObiVF1Q{3%7#J9ii!d-~
zGB7aw5P^i8k|+a%8Uq7^u_#15N|b>?nSp_!MHCXkD?}L>R2Uc->d!$Heimh5$Yo$)
zkP>5HkY`|E=n#V#v_cFLlsm;BL3R?#zbpnx?T^J67#JZ%1(*bt5&8@a3`z_P40a3*
z4C-J}h_69R2N1yki4Fz^hRN+LimW!E@@Mi|7HLllP~<Q$FgP+WFj#?{4^?f?0PzOM
z>mVT`P(}x3ZU%_=LD@kMBmu=HlLc9|V|5uIfdESErcfD6C=DtqbU^-PU|=v~fW!`{
z`~pb}GeFWYDCvRtpcDW~W}xB;lsrMjitXl^tWHduAFxkg<}%VXvQRKGv@$fBT*Y0x
OnTaQYb#uDlR#pIeICty-

diff --git a/sopds_web_backend/locale/ru/LC_MESSAGES/django.po b/sopds_web_backend/locale/ru/LC_MESSAGES/django.po
index 70d5511..45b8d5d 100644
--- a/sopds_web_backend/locale/ru/LC_MESSAGES/django.po
+++ b/sopds_web_backend/locale/ru/LC_MESSAGES/django.po
@@ -1,362 +1,367 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-02-28 21:12+0300\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
-"10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%"
-"100>=11 && n%100<=14)? 2 : 3);\n"
-
-#: .\sopds_web_backend\templates\admin\base.html:30
-msgid "Welcome,"
-msgstr ""
-
-#: .\sopds_web_backend\templates\admin\base.html:35
-#, fuzzy
-#| msgid "File size:"
-msgid "View site"
-msgstr "Размер файла:"
-
-#: .\sopds_web_backend\templates\admin\base.html:40
-msgid "Documentation"
-msgstr ""
-
-#: .\sopds_web_backend\templates\admin\base.html:44
-#, fuzzy
-#| msgid "Enter Password"
-msgid "Change password"
-msgstr "Введите пароль"
-
-#: .\sopds_web_backend\templates\admin\base.html:46
-#, fuzzy
-#| msgid "Logout"
-msgid "Log out"
-msgstr "Выход"
-
-#: .\sopds_web_backend\templates\admin\base.html:56
-msgid "Home"
-msgstr ""
-
-#: .\sopds_web_backend\templates\sopds_authors.html:8
-#, python-format
-msgid "Total: %(a_book_count)s books."
-msgstr "Всего: %(a_book_count)s книг."
-
-#: .\sopds_web_backend\templates\sopds_authors.html:17
-#: .\sopds_web_backend\templates\sopds_books.html:99
-#: .\sopds_web_backend\templates\sopds_catalogs.html:42
-#: .\sopds_web_backend\templates\sopds_series.html:17
-msgid "Previous page"
-msgstr "Назад"
-
-#: .\sopds_web_backend\templates\sopds_authors.html:32
-#: .\sopds_web_backend\templates\sopds_books.html:114
-#: .\sopds_web_backend\templates\sopds_catalogs.html:57
-#: .\sopds_web_backend\templates\sopds_series.html:32
-msgid "Next page"
-msgstr "Вперед"
-
-#: .\sopds_web_backend\templates\sopds_books.html:15
-msgid "Confirm the deletion of the book to your bookshelf."
-msgstr "Подтвердите удаление книги с Вашей книжной полки."
-
-#: .\sopds_web_backend\templates\sopds_books.html:25
-msgid "Delete"
-msgstr "Удалить"
-
-#: .\sopds_web_backend\templates\sopds_books.html:26
-#: .\sopds_web_backend\templates\sopds_books.html:37
-msgid "Cancel"
-msgstr "Отмена"
-
-#: .\sopds_web_backend\templates\sopds_books.html:34
-msgid "Confirm to clear your bookshelf."
-msgstr "Подтвердите очистку Вашей книжной полки."
-
-#: .\sopds_web_backend\templates\sopds_books.html:36
-msgid "Clear"
-msgstr "Очистить"
-
-#: .\sopds_web_backend\templates\sopds_books.html:43
-msgid "Clear bookshelf"
-msgstr "Очистить книжную полку"
-
-#: .\sopds_web_backend\templates\sopds_books.html:49
-msgid "Download:"
-msgstr "Скачать:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:59
-msgid "Delete from bookshelf"
-msgstr "Удалить с книжной полки"
-
-#: .\sopds_web_backend\templates\sopds_books.html:69
-msgid "Book title:"
-msgstr "Название книги:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:71
-msgid "Authors:"
-msgstr "Авторы:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:74
-#: .\sopds_web_backend\templates\sopds_menu.html:9
-#: .\sopds_web_backend\templates\sopds_menu.html:31
-#: .\sopds_web_backend\views.py:481 .\sopds_web_backend\views.py:485
-msgid "Genres"
-msgstr "Жанры"
-
-#: .\sopds_web_backend\templates\sopds_books.html:77
-#: .\sopds_web_backend\templates\sopds_logo.html:29
-#: .\sopds_web_backend\templates\sopds_menu.html:10
-#: .\sopds_web_backend\templates\sopds_menu.html:33
-#: .\sopds_web_backend\views.py:267 .\sopds_web_backend\views.py:466
-msgid "Series"
-msgstr "Серии"
-
-#: .\sopds_web_backend\templates\sopds_books.html:79
-msgid "File:"
-msgstr "Файл:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:80
-msgid "File size:"
-msgstr "Размер файла:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:81
-msgid "Changes date:"
-msgstr "Дата правки:"
-
-#: .\sopds_web_backend\templates\sopds_books.html:83
-msgid "Doubles for book:"
-msgstr "Дубликаты книги:"
-
-#: .\sopds_web_backend\templates\sopds_breadcrumbs.html:3
-msgid "You are here:"
-msgstr "Вы здесь:"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:6
-msgid "BOOKSHELF"
-msgstr "КНИЖНАЯ ПОЛКА"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:19
-msgid ""
-"Bookshelf is available only SimpleOPDS Catalog mode with activated user "
-"authorization."
-msgstr ""
-"Книжная полка доступна только в режиме работы SimpleOPDS Catalog со "
-"включенной авторизацией пользователей."
-
-#: .\sopds_web_backend\templates\sopds_footer.html:23
-msgid "STATISTICS"
-msgstr "СТАТИСТИКА"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:25
-msgid "This сatalog contains:"
-msgstr "Этот каталог содержит:"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:26
-msgid "books,"
-msgstr "книг,"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:27
-msgid "authors,"
-msgstr "авторов,"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:28
-msgid "genres and"
-msgstr "жанров и"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:29
-msgid "series."
-msgstr "серий."
-
-#: .\sopds_web_backend\templates\sopds_footer.html:32
-msgid "Last collection scan date:"
-msgstr "Дата последнего сканирования:"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:33
-msgid "Never"
-msgstr "Никогда"
-
-#: .\sopds_web_backend\templates\sopds_footer.html:38
-msgid "RANDOM BOOK"
-msgstr "СЛУЧАЙНАЯ КНИГА"
-
-#: .\sopds_web_backend\templates\sopds_hello.html:7
-msgid "Hello"
-msgstr "Здравствуйте"
-
-#: .\sopds_web_backend\templates\sopds_hello.html:7
-msgid "Guest"
-msgstr "Гость"
-
-#: .\sopds_web_backend\templates\sopds_hello.html:9
-msgid ""
-"Simple OPDS Catalog - is a free program for Linux and Windows, which allows "
-"for the rapid creation of electronic OPDS-catalog books. OPDS (Open "
-"Publication Distribution System) directory allows you to access your library "
-"through the Internet with many devices for reading electronic books, "
-"tablets, smartphones, etc. More about the program can be found on the "
-"project website:"
-msgstr ""
-"Simple OPDS Catalog - Бесплатная программа для операционных систем Linux и "
-"Windows, предназначенная для быстрого создания электронного OPDS-каталога "
-"книг. OPDS (Open Publication Distribution System) каталог позволяет получать "
-"доступ к Вашей библиотеке через Интернет с большинства устройств для чтения "
-"электронных книг, планшетов, смартфонов и т.д. Дополнительную информацию о "
-"программе Вы сможете найти на Web-сайте проекта:"
-
-#: .\sopds_web_backend\templates\sopds_login.html:9
-msgid "Username"
-msgstr "Имя пользователя"
-
-#: .\sopds_web_backend\templates\sopds_login.html:10
-msgid "Enter Username"
-msgstr "Введите имя"
-
-#: .\sopds_web_backend\templates\sopds_login.html:12
-msgid "Password"
-msgstr "Пароль"
-
-#: .\sopds_web_backend\templates\sopds_login.html:13
-msgid "Enter Password"
-msgstr "Введите пароль"
-
-#: .\sopds_web_backend\templates\sopds_login.html:15
-msgid "Log in"
-msgstr "Вход"
-
-#: .\sopds_web_backend\templates\sopds_logo.html:14
-#: .\sopds_web_backend\views.py:267 .\sopds_web_backend\views.py:306
-msgid "Search"
-msgstr "Найти"
-
-#: .\sopds_web_backend\templates\sopds_logo.html:26
-msgid "Choose Search Type:"
-msgstr "Выберите тип поиска:"
-
-#: .\sopds_web_backend\templates\sopds_logo.html:27
-msgid "Title"
-msgstr "Название"
-
-#: .\sopds_web_backend\templates\sopds_logo.html:28
-msgid "Author"
-msgstr "Автор"
-
-#: .\sopds_web_backend\templates\sopds_menu.html:6
-#: .\sopds_web_backend\templates\sopds_menu.html:16
-#: .\sopds_web_backend\views.py:364
-msgid "Catalogs"
-msgstr "Каталоги"
-
-#: .\sopds_web_backend\templates\sopds_menu.html:7
-#: .\sopds_web_backend\templates\sopds_menu.html:17
-#: .\sopds_web_backend\views.py:89 .\sopds_web_backend\views.py:95
-#: .\sopds_web_backend\views.py:108 .\sopds_web_backend\views.py:120
-#: .\sopds_web_backend\views.py:129 .\sopds_web_backend\views.py:132
-#: .\sopds_web_backend\views.py:141 .\sopds_web_backend\views.py:145
-#: .\sopds_web_backend\views.py:155 .\sopds_web_backend\views.py:167
-#: .\sopds_web_backend\views.py:398
-msgid "Books"
-msgstr "Книги"
-
-#: .\sopds_web_backend\templates\sopds_menu.html:8
-#: .\sopds_web_backend\templates\sopds_menu.html:24
-#: .\sopds_web_backend\views.py:306 .\sopds_web_backend\views.py:432
-msgid "Authors"
-msgstr "Авторы"
-
-#: .\sopds_web_backend\templates\sopds_selectauthor.html:16
-#, python-format
-msgid "Total: %(chars_cnt)s authors."
-msgstr "Всего: %(chars_cnt)s авторов."
-
-#: .\sopds_web_backend\templates\sopds_selectbook.html:16
-#, python-format
-msgid "Total: %(chars_cnt)s books."
-msgstr "Всего: %(chars_cnt)s книг."
-
-#: .\sopds_web_backend\templates\sopds_selectgenres.html:16
-#, python-format
-msgid "Total: %(g_num_book)s books."
-msgstr "Всего: %(g_num_book)s книг."
-
-#: .\sopds_web_backend\templates\sopds_selectseries.html:16
-#, python-format
-msgid "Total: %(chars_cnt)s series."
-msgstr "Всего: %(chars_cnt)s серий."
-
-#: .\sopds_web_backend\templates\sopds_series.html:8
-#, python-format
-msgid "Total: %(s_book_count)s books."
-msgstr "Всего: %(s_book_count)s книг."
-
-#: .\sopds_web_backend\templates\sopds_top.html:19
-#: .\sopds_web_backend\views.py:546
-msgid "Logout"
-msgstr "Выход"
-
-#: .\sopds_web_backend\templates\sopds_top.html:21
-msgid "Settings"
-msgstr "Настройки"
-
-#: .\sopds_web_backend\templates\sopds_top.html:24
-#: .\sopds_web_backend\views.py:518
-msgid "Login"
-msgstr "Вход"
-
-#: .\sopds_web_backend\views.py:89 .\sopds_web_backend\views.py:95
-msgid "Search by title"
-msgstr "Поиск по наименованию"
-
-#: .\sopds_web_backend\views.py:108
-msgid "Search by author"
-msgstr "Поиск по автору"
-
-#: .\sopds_web_backend\views.py:120
-msgid "Search by series"
-msgstr "Поиск по серии"
-
-#: .\sopds_web_backend\views.py:129 .\sopds_web_backend\views.py:132
-msgid "Search by genre"
-msgstr "Поиск по жанру"
-
-#: .\sopds_web_backend\views.py:141 .\sopds_web_backend\views.py:145
-msgid "Bookshelf"
-msgstr "Книжная полка"
-
-#: .\sopds_web_backend\views.py:155
-msgid "Doubles for book"
-msgstr "Дубликаты книги"
-
-#: .\sopds_web_backend\views.py:361
-msgid "ROOT"
-msgstr "НАЧАЛО"
-
-#: .\sopds_web_backend\views.py:398 .\sopds_web_backend\views.py:432
-#: .\sopds_web_backend\views.py:466 .\sopds_web_backend\views.py:481
-#: .\sopds_web_backend\views.py:485
-msgid "Select"
-msgstr "Выбор"
-
-#: .\sopds_web_backend\views.py:513
-msgid "HOME"
-msgstr "ГЛАВНАЯ"
-
-#: .\sopds_web_backend\views.py:534
-msgid "This account is not active!"
-msgstr "Учетная запись не активна!"
-
-#: .\sopds_web_backend\views.py:537
-msgid "User does not exist or the password is incorrect!"
-msgstr "Пользователь не существует или введен неправильный пароль!"
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-03-23 22:58+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
+"%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: sopds_web_backend/templates/admin/base.html:30
+msgid "Welcome,"
+msgstr ""
+
+#: sopds_web_backend/templates/admin/base.html:35
+#, fuzzy
+#| msgid "File size:"
+msgid "View site"
+msgstr "Размер файла:"
+
+#: sopds_web_backend/templates/admin/base.html:40
+msgid "Documentation"
+msgstr ""
+
+#: sopds_web_backend/templates/admin/base.html:44
+#, fuzzy
+#| msgid "Enter Password"
+msgid "Change password"
+msgstr "Введите пароль"
+
+#: sopds_web_backend/templates/admin/base.html:46
+#, fuzzy
+#| msgid "Logout"
+msgid "Log out"
+msgstr "Выход"
+
+#: sopds_web_backend/templates/admin/base.html:56
+msgid "Home"
+msgstr ""
+
+#: sopds_web_backend/templates/sopds_authors.html:8
+#, python-format
+msgid "Total: %(a_book_count)s books."
+msgstr "Всего: %(a_book_count)s книг."
+
+#: sopds_web_backend/templates/sopds_authors.html:17
+#: sopds_web_backend/templates/sopds_books.html:102
+#: sopds_web_backend/templates/sopds_catalogs.html:42
+#: sopds_web_backend/templates/sopds_series.html:17
+msgid "Previous page"
+msgstr "Назад"
+
+#: sopds_web_backend/templates/sopds_authors.html:32
+#: sopds_web_backend/templates/sopds_books.html:117
+#: sopds_web_backend/templates/sopds_catalogs.html:57
+#: sopds_web_backend/templates/sopds_series.html:32
+msgid "Next page"
+msgstr "Вперед"
+
+#: sopds_web_backend/templates/sopds_books.html:15
+msgid "Confirm the deletion of the book to your bookshelf."
+msgstr "Подтвердите удаление книги с Вашей книжной полки."
+
+#: sopds_web_backend/templates/sopds_books.html:25
+msgid "Delete"
+msgstr "Удалить"
+
+#: sopds_web_backend/templates/sopds_books.html:26
+#: sopds_web_backend/templates/sopds_books.html:37
+msgid "Cancel"
+msgstr "Отмена"
+
+#: sopds_web_backend/templates/sopds_books.html:34
+msgid "Confirm to clear your bookshelf."
+msgstr "Подтвердите очистку Вашей книжной полки."
+
+#: sopds_web_backend/templates/sopds_books.html:36
+msgid "Clear"
+msgstr "Очистить"
+
+#: sopds_web_backend/templates/sopds_books.html:43
+msgid "Clear bookshelf"
+msgstr "Очистить книжную полку"
+
+#: sopds_web_backend/templates/sopds_books.html:49
+msgid "Download:"
+msgstr "Скачать:"
+
+#: sopds_web_backend/templates/sopds_books.html:60
+msgid "Read"
+msgstr "Читать"
+
+#: sopds_web_backend/templates/sopds_books.html:62
+msgid "Delete from bookshelf"
+msgstr "Удалить с книжной полки"
+
+#: sopds_web_backend/templates/sopds_books.html:72
+msgid "Book title:"
+msgstr "Название книги:"
+
+#: sopds_web_backend/templates/sopds_books.html:74
+msgid "Authors:"
+msgstr "Авторы:"
+
+#: sopds_web_backend/templates/sopds_books.html:77
+#: sopds_web_backend/templates/sopds_menu.html:9
+#: sopds_web_backend/templates/sopds_menu.html:31
+#: sopds_web_backend/views.py:484 sopds_web_backend/views.py:488
+msgid "Genres"
+msgstr "Жанры"
+
+#: sopds_web_backend/templates/sopds_books.html:80
+#: sopds_web_backend/templates/sopds_logo.html:29
+#: sopds_web_backend/templates/sopds_menu.html:10
+#: sopds_web_backend/templates/sopds_menu.html:33
+#: sopds_web_backend/views.py:270 sopds_web_backend/views.py:469
+msgid "Series"
+msgstr "Серии"
+
+#: sopds_web_backend/templates/sopds_books.html:82
+msgid "File:"
+msgstr "Файл:"
+
+#: sopds_web_backend/templates/sopds_books.html:83
+msgid "File size:"
+msgstr "Размер файла:"
+
+#: sopds_web_backend/templates/sopds_books.html:84
+msgid "Changes date:"
+msgstr "Дата правки:"
+
+#: sopds_web_backend/templates/sopds_books.html:86
+msgid "Doubles for book:"
+msgstr "Дубликаты книги:"
+
+#: sopds_web_backend/templates/sopds_breadcrumbs.html:3
+msgid "You are here:"
+msgstr "Вы здесь:"
+
+#: sopds_web_backend/templates/sopds_footer.html:6
+msgid "BOOKSHELF"
+msgstr "КНИЖНАЯ ПОЛКА"
+
+#: sopds_web_backend/templates/sopds_footer.html:19
+msgid ""
+"Bookshelf is available only SimpleOPDS Catalog mode with activated user "
+"authorization."
+msgstr ""
+"Книжная полка доступна только в режиме работы SimpleOPDS Catalog со "
+"включенной авторизацией пользователей."
+
+#: sopds_web_backend/templates/sopds_footer.html:23
+msgid "STATISTICS"
+msgstr "СТАТИСТИКА"
+
+#: sopds_web_backend/templates/sopds_footer.html:25
+msgid "This сatalog contains:"
+msgstr "Этот каталог содержит:"
+
+#: sopds_web_backend/templates/sopds_footer.html:26
+msgid "books,"
+msgstr "книг,"
+
+#: sopds_web_backend/templates/sopds_footer.html:27
+msgid "authors,"
+msgstr "авторов,"
+
+#: sopds_web_backend/templates/sopds_footer.html:28
+msgid "genres and"
+msgstr "жанров и"
+
+#: sopds_web_backend/templates/sopds_footer.html:29
+msgid "series."
+msgstr "серий."
+
+#: sopds_web_backend/templates/sopds_footer.html:32
+msgid "Last collection scan date:"
+msgstr "Дата последнего сканирования:"
+
+#: sopds_web_backend/templates/sopds_footer.html:33
+msgid "Never"
+msgstr "Никогда"
+
+#: sopds_web_backend/templates/sopds_footer.html:38
+msgid "RANDOM BOOK"
+msgstr "СЛУЧАЙНАЯ КНИГА"
+
+#: sopds_web_backend/templates/sopds_hello.html:7
+msgid "Hello"
+msgstr "Здравствуйте"
+
+#: sopds_web_backend/templates/sopds_hello.html:7
+msgid "Guest"
+msgstr "Гость"
+
+#: sopds_web_backend/templates/sopds_hello.html:9
+msgid ""
+"Simple OPDS Catalog - is a free program for Linux and Windows, which allows "
+"for the rapid creation of electronic OPDS-catalog books. OPDS (Open "
+"Publication Distribution System) directory allows you to access your library "
+"through the Internet with many devices for reading electronic books, "
+"tablets, smartphones, etc. More about the program can be found on the "
+"project website:"
+msgstr ""
+"Simple OPDS Catalog - Бесплатная программа для операционных систем Linux и "
+"Windows, предназначенная для быстрого создания электронного OPDS-каталога "
+"книг. OPDS (Open Publication Distribution System) каталог позволяет получать "
+"доступ к Вашей библиотеке через Интернет с большинства устройств для чтения "
+"электронных книг, планшетов, смартфонов и т.д. Дополнительную информацию о "
+"программе Вы сможете найти на Web-сайте проекта:"
+
+#: sopds_web_backend/templates/sopds_login.html:9
+msgid "Username"
+msgstr "Имя пользователя"
+
+#: sopds_web_backend/templates/sopds_login.html:10
+msgid "Enter Username"
+msgstr "Введите имя"
+
+#: sopds_web_backend/templates/sopds_login.html:12
+msgid "Password"
+msgstr "Пароль"
+
+#: sopds_web_backend/templates/sopds_login.html:13
+msgid "Enter Password"
+msgstr "Введите пароль"
+
+#: sopds_web_backend/templates/sopds_login.html:15
+msgid "Log in"
+msgstr "Вход"
+
+#: sopds_web_backend/templates/sopds_logo.html:14
+#: sopds_web_backend/views.py:270 sopds_web_backend/views.py:309
+msgid "Search"
+msgstr "Найти"
+
+#: sopds_web_backend/templates/sopds_logo.html:26
+msgid "Choose Search Type:"
+msgstr "Выберите тип поиска:"
+
+#: sopds_web_backend/templates/sopds_logo.html:27
+msgid "Title"
+msgstr "Название"
+
+#: sopds_web_backend/templates/sopds_logo.html:28
+msgid "Author"
+msgstr "Автор"
+
+#: sopds_web_backend/templates/sopds_menu.html:6
+#: sopds_web_backend/templates/sopds_menu.html:16
+#: sopds_web_backend/views.py:367
+msgid "Catalogs"
+msgstr "Каталоги"
+
+#: sopds_web_backend/templates/sopds_menu.html:7
+#: sopds_web_backend/templates/sopds_menu.html:17
+#: sopds_web_backend/views.py:92 sopds_web_backend/views.py:98
+#: sopds_web_backend/views.py:111 sopds_web_backend/views.py:123
+#: sopds_web_backend/views.py:132 sopds_web_backend/views.py:135
+#: sopds_web_backend/views.py:144 sopds_web_backend/views.py:148
+#: sopds_web_backend/views.py:158 sopds_web_backend/views.py:170
+#: sopds_web_backend/views.py:401
+msgid "Books"
+msgstr "Книги"
+
+#: sopds_web_backend/templates/sopds_menu.html:8
+#: sopds_web_backend/templates/sopds_menu.html:24
+#: sopds_web_backend/views.py:309 sopds_web_backend/views.py:435
+msgid "Authors"
+msgstr "Авторы"
+
+#: sopds_web_backend/templates/sopds_selectauthor.html:16
+#, python-format
+msgid "Total: %(chars_cnt)s authors."
+msgstr "Всего: %(chars_cnt)s авторов."
+
+#: sopds_web_backend/templates/sopds_selectbook.html:16
+#, python-format
+msgid "Total: %(chars_cnt)s books."
+msgstr "Всего: %(chars_cnt)s книг."
+
+#: sopds_web_backend/templates/sopds_selectgenres.html:16
+#, python-format
+msgid "Total: %(g_num_book)s books."
+msgstr "Всего: %(g_num_book)s книг."
+
+#: sopds_web_backend/templates/sopds_selectseries.html:16
+#, python-format
+msgid "Total: %(chars_cnt)s series."
+msgstr "Всего: %(chars_cnt)s серий."
+
+#: sopds_web_backend/templates/sopds_series.html:8
+#, python-format
+msgid "Total: %(s_book_count)s books."
+msgstr "Всего: %(s_book_count)s книг."
+
+#: sopds_web_backend/templates/sopds_top.html:19
+#: sopds_web_backend/views.py:549
+msgid "Logout"
+msgstr "Выход"
+
+#: sopds_web_backend/templates/sopds_top.html:21
+msgid "Settings"
+msgstr "Настройки"
+
+#: sopds_web_backend/templates/sopds_top.html:24
+#: sopds_web_backend/views.py:521
+msgid "Login"
+msgstr "Вход"
+
+#: sopds_web_backend/views.py:92 sopds_web_backend/views.py:98
+msgid "Search by title"
+msgstr "Поиск по наименованию"
+
+#: sopds_web_backend/views.py:111
+msgid "Search by author"
+msgstr "Поиск по автору"
+
+#: sopds_web_backend/views.py:123
+msgid "Search by series"
+msgstr "Поиск по серии"
+
+#: sopds_web_backend/views.py:132 sopds_web_backend/views.py:135
+msgid "Search by genre"
+msgstr "Поиск по жанру"
+
+#: sopds_web_backend/views.py:144 sopds_web_backend/views.py:148
+msgid "Bookshelf"
+msgstr "Книжная полка"
+
+#: sopds_web_backend/views.py:158
+msgid "Doubles for book"
+msgstr "Дубликаты книги"
+
+#: sopds_web_backend/views.py:364
+msgid "ROOT"
+msgstr "НАЧАЛО"
+
+#: sopds_web_backend/views.py:401 sopds_web_backend/views.py:435
+#: sopds_web_backend/views.py:469 sopds_web_backend/views.py:484
+#: sopds_web_backend/views.py:488
+msgid "Select"
+msgstr "Выбор"
+
+#: sopds_web_backend/views.py:516
+msgid "HOME"
+msgstr "ГЛАВНАЯ"
+
+#: sopds_web_backend/views.py:537
+msgid "This account is not active!"
+msgstr "Учетная запись не активна!"
+
+#: sopds_web_backend/views.py:540
+msgid "User does not exist or the password is incorrect!"
+msgstr "Пользователь не существует или введен неправильный пароль!"
diff --git a/sopds_web_backend/templates/sopds_books.html b/sopds_web_backend/templates/sopds_books.html
index 4ead100..700b941 100644
--- a/sopds_web_backend/templates/sopds_books.html
+++ b/sopds_web_backend/templates/sopds_books.html
@@ -57,6 +57,7 @@
 			{% if b.format == 'fb2' and fb2tomobi %}
 			   <i><a href="{% url 'opds_catalog:convert' b.id 'mobi' %}"><span class="label small">mobi</span></a></i>&nbsp;
 			{% endif %}			
+            <i><a href="{% url 'opds_catalog:read' b.id %}"><span class="label small">{% trans "Read" %}</span></a></i>&nbsp;
 			{% if isbookshelf %}
 			&nbsp;&nbsp;<i><a href="#" onclick="del_bsbook({{ b.id }},'{{b.title}}');"><span class="secondary label small">&nbsp;{% trans "Delete from bookshelf" %}&nbsp;</span></a></i>
 		    {% endif %}
-- 
GitLab