mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Get Books: Remove epub bud store. Add Ozon.ru store. Fix broken amazon UK and DE stores. Fixes #816091 (Epub bud store steals ebooks. Do not direct people there.)
This commit is contained in:
commit
42f9160af0
@ -1228,17 +1228,6 @@ class StoreEbookscomStore(StoreBase):
|
||||
formats = ['EPUB', 'LIT', 'MOBI', 'PDF']
|
||||
affiliate = True
|
||||
|
||||
#class StoreEPubBuyDEStore(StoreBase):
|
||||
# name = 'EPUBBuy DE'
|
||||
# author = 'Charles Haley'
|
||||
# description = u'Bei EPUBBuy.com finden Sie ausschliesslich eBooks im weitverbreiteten EPUB-Format und ohne DRM. So haben Sie die freie Wahl, wo Sie Ihr eBook lesen: Tablet, eBook-Reader, Smartphone oder einfach auf Ihrem PC. So macht eBook-Lesen Spaß!'
|
||||
# actual_plugin = 'calibre.gui2.store.stores.epubbuy_de_plugin:EPubBuyDEStore'
|
||||
#
|
||||
# drm_free_only = True
|
||||
# headquarters = 'DE'
|
||||
# formats = ['EPUB']
|
||||
# affiliate = True
|
||||
|
||||
class StoreEBookShoppeUKStore(StoreBase):
|
||||
name = 'ebookShoppe UK'
|
||||
author = u'Charles Haley'
|
||||
@ -1266,16 +1255,7 @@ class StoreEKnigiStore(StoreBase):
|
||||
|
||||
headquarters = 'BG'
|
||||
formats = ['EPUB', 'PDF', 'HTML']
|
||||
#affiliate = True
|
||||
|
||||
class StoreEpubBudStore(StoreBase):
|
||||
name = 'ePub Bud'
|
||||
description = 'Well, it\'s pretty much just "YouTube for Children\'s eBooks. A not-for-profit organization devoted to brining self published childrens books to the world.'
|
||||
actual_plugin = 'calibre.gui2.store.stores.epubbud_plugin:EpubBudStore'
|
||||
|
||||
drm_free_only = True
|
||||
headquarters = 'US'
|
||||
formats = ['EPUB']
|
||||
affiliate = True
|
||||
|
||||
class StoreFeedbooksStore(StoreBase):
|
||||
name = 'Feedbooks'
|
||||
@ -1311,6 +1291,7 @@ class StoreGoogleBooksStore(StoreBase):
|
||||
|
||||
headquarters = 'US'
|
||||
formats = ['EPUB', 'PDF', 'TXT']
|
||||
affiliate = True
|
||||
|
||||
class StoreGutenbergStore(StoreBase):
|
||||
name = 'Project Gutenberg'
|
||||
@ -1394,6 +1375,17 @@ class StoreOReillyStore(StoreBase):
|
||||
headquarters = 'US'
|
||||
formats = ['APK', 'DAISY', 'EPUB', 'MOBI', 'PDF']
|
||||
|
||||
class StoreOzonRUStore(StoreBase):
|
||||
name = 'OZON.ru'
|
||||
description = u'ebooks from OZON.ru'
|
||||
actual_plugin = 'calibre.gui2.store.stores.ozon_ru_plugin:OzonRUStore'
|
||||
author = 'Roman Mukhin'
|
||||
|
||||
drm_free_only = True
|
||||
headquarters = 'RU'
|
||||
formats = ['TXT', 'PDF', 'DJVU', 'RTF', 'DOC', 'JAR', 'FB2']
|
||||
affiliate = True
|
||||
|
||||
class StorePragmaticBookshelfStore(StoreBase):
|
||||
name = 'Pragmatic Bookshelf'
|
||||
description = u'The Pragmatic Bookshelf\'s collection of programming and tech books avaliable as ebooks.'
|
||||
@ -1491,10 +1483,8 @@ plugins += [
|
||||
StoreEbookNLStore,
|
||||
StoreEbookscomStore,
|
||||
StoreEBookShoppeUKStore,
|
||||
# StoreEPubBuyDEStore,
|
||||
StoreEHarlequinStore,
|
||||
StoreEKnigiStore,
|
||||
StoreEpubBudStore,
|
||||
StoreFeedbooksStore,
|
||||
StoreFoylesUKStore,
|
||||
StoreGandalfStore,
|
||||
@ -1508,6 +1498,7 @@ plugins += [
|
||||
StoreNextoStore,
|
||||
StoreOpenBooksStore,
|
||||
StoreOReillyStore,
|
||||
StoreOzonRUStore,
|
||||
StorePragmaticBookshelfStore,
|
||||
StoreSmashwordsStore,
|
||||
StoreVirtualoStore,
|
||||
|
@ -24,10 +24,9 @@ XPath = partial(etree.XPath, namespaces=NAMESPACES)
|
||||
tostring = partial(etree.tostring, method='text', encoding=unicode)
|
||||
|
||||
def get_metadata(stream):
|
||||
""" Return fb2 metadata as a L{MetaInformation} object """
|
||||
''' Return fb2 metadata as a L{MetaInformation} object '''
|
||||
|
||||
root = _get_fbroot(stream)
|
||||
|
||||
book_title = _parse_book_title(root)
|
||||
authors = _parse_authors(root)
|
||||
|
||||
@ -166,7 +165,7 @@ def _parse_tags(root, mi):
|
||||
break
|
||||
|
||||
def _parse_series(root, mi):
|
||||
#calibri supports only 1 series: use the 1-st one
|
||||
# calibri supports only 1 series: use the 1-st one
|
||||
# pick up sequence but only from 1 secrion in prefered order
|
||||
# except <src-title-info>
|
||||
xp_ti = '//fb2:title-info/fb2:sequence[1]'
|
||||
@ -181,11 +180,12 @@ def _parse_series(root, mi):
|
||||
def _parse_isbn(root, mi):
|
||||
# some people try to put several isbn in this field, but it is not allowed. try to stick to the 1-st one in this case
|
||||
isbn = XPath('normalize-space(//fb2:publish-info/fb2:isbn/text())')(root)
|
||||
# some people try to put several isbn in this field, but it is not allowed. try to stick to the 1-st one in this case
|
||||
if ',' in isbn:
|
||||
isbn = isbn[:isbn.index(',')]
|
||||
if check_isbn(isbn):
|
||||
mi.isbn = isbn
|
||||
if isbn:
|
||||
# some people try to put several isbn in this field, but it is not allowed. try to stick to the 1-st one in this case
|
||||
if ',' in isbn:
|
||||
isbn = isbn[:isbn.index(',')]
|
||||
if check_isbn(isbn):
|
||||
mi.isbn = isbn
|
||||
|
||||
def _parse_comments(root, mi):
|
||||
# pick up annotation but only from 1 secrion <title-info>; fallback: <src-title-info>
|
||||
@ -232,4 +232,3 @@ def _get_fbroot(stream):
|
||||
raw = xml_to_unicode(raw, strip_encoding_pats=True)[0]
|
||||
root = etree.fromstring(raw, parser=parser)
|
||||
return root
|
||||
|
||||
|
@ -23,7 +23,8 @@ from calibre.utils.search_query_parser import SearchQueryParser
|
||||
|
||||
def comparable_price(text):
|
||||
text = re.sub(r'[^0-9.,]', '', text)
|
||||
if len(text) < 3 or text[-3] not in ('.', ','):
|
||||
delimeter = (',', '.')
|
||||
if len(text) < 3 or text[-3] not in delimeter:
|
||||
text += '00'
|
||||
text = re.sub(r'\D', '', text)
|
||||
text = text.rjust(6, '0')
|
||||
@ -334,6 +335,11 @@ class SearchFilter(SearchQueryParser):
|
||||
}
|
||||
for x in ('author', 'download', 'format'):
|
||||
q[x+'s'] = q[x]
|
||||
|
||||
# make the price in query the same format as result
|
||||
if location == 'price':
|
||||
query = comparable_price(query)
|
||||
|
||||
for sr in self.srs:
|
||||
for locvalue in locations:
|
||||
accessor = q[locvalue]
|
||||
|
@ -45,24 +45,26 @@ class AmazonDEKindleStore(StorePlugin):
|
||||
doc = html.fromstring(f.read())
|
||||
|
||||
# Amazon has two results pages.
|
||||
is_shot = doc.xpath('boolean(//div[@id="shotgunMainResults"])')
|
||||
# Horizontal grid of books.
|
||||
if is_shot:
|
||||
data_xpath = '//div[contains(@class, "result")]'
|
||||
format_xpath = './/div[@class="productTitle"]/text()'
|
||||
cover_xpath = './/div[@class="productTitle"]//img/@src'
|
||||
# Vertical list of books.
|
||||
else:
|
||||
data_xpath = '//div[@class="productData"]'
|
||||
format_xpath = './/span[@class="format"]/text()'
|
||||
cover_xpath = '../div[@class="productImage"]/a/img/@src'
|
||||
# 20110725: seems that is_shot is gone.
|
||||
# is_shot = doc.xpath('boolean(//div[@id="shotgunMainResults"])')
|
||||
# # Horizontal grid of books.
|
||||
# if is_shot:
|
||||
# data_xpath = '//div[contains(@class, "result")]'
|
||||
# format_xpath = './/div[@class="productTitle"]/text()'
|
||||
# cover_xpath = './/div[@class="productTitle"]//img/@src'
|
||||
# # Vertical list of books.
|
||||
# else:
|
||||
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
|
||||
format_xpath = './/span[@class="format"]/text()'
|
||||
cover_xpath = './/img[@class="productImage"]/@src'
|
||||
# end is_shot else
|
||||
|
||||
for data in doc.xpath(data_xpath):
|
||||
if counter <= 0:
|
||||
break
|
||||
|
||||
# Even though we are searching digital-text only Amazon will still
|
||||
# put in results for non Kindle books (author pages). Se we need
|
||||
# put in results for non Kindle books (author pages). So we need
|
||||
# to explicitly check if the item is a Kindle book and ignore it
|
||||
# if it isn't.
|
||||
format = ''.join(data.xpath(format_xpath))
|
||||
@ -71,28 +73,18 @@ class AmazonDEKindleStore(StorePlugin):
|
||||
|
||||
# We must have an asin otherwise we can't easily reference the
|
||||
# book later.
|
||||
asin_href = None
|
||||
asin_a = data.xpath('.//div[@class="productTitle"]/a[1]')
|
||||
if asin_a:
|
||||
asin_href = asin_a[0].get('href', '')
|
||||
m = re.search(r'/dp/(?P<asin>.+?)(/|$)', asin_href)
|
||||
if m:
|
||||
asin = m.group('asin')
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
asin = ''.join(data.xpath("@name"))
|
||||
|
||||
cover_url = ''.join(data.xpath(cover_xpath))
|
||||
|
||||
title = ''.join(data.xpath('.//div[@class="productTitle"]/a/text()'))
|
||||
title = ''.join(data.xpath('.//div[@class="title"]/a/text()'))
|
||||
price = ''.join(data.xpath('.//div[@class="newPrice"]/span/text()'))
|
||||
|
||||
if is_shot:
|
||||
author = format.split(' von ')[-1]
|
||||
else:
|
||||
author = ''.join(data.xpath('.//div[@class="productTitle"]/span[@class="ptBrand"]/text()'))
|
||||
author = author.split(' von ')[-1]
|
||||
# if is_shot:
|
||||
# author = format.split(' von ')[-1]
|
||||
# else:
|
||||
author = ''.join(data.xpath('.//div[@class="title"]/span[@class="ptBrand"]/text()'))
|
||||
author = author.split('von ')[-1]
|
||||
|
||||
counter -= 1
|
||||
|
||||
|
@ -42,49 +42,56 @@ class AmazonUKKindleStore(StorePlugin):
|
||||
doc = html.fromstring(f.read())
|
||||
|
||||
# Amazon has two results pages.
|
||||
is_shot = doc.xpath('boolean(//div[@id="shotgunMainResults"])')
|
||||
# Horizontal grid of books.
|
||||
if is_shot:
|
||||
data_xpath = '//div[contains(@class, "result")]'
|
||||
cover_xpath = './/div[@class="productTitle"]//img/@src'
|
||||
# Vertical list of books.
|
||||
else:
|
||||
data_xpath = '//div[contains(@class, "product")]'
|
||||
cover_xpath = './div[@class="productImage"]/a/img/@src'
|
||||
# 20110725: seems that is_shot is gone.
|
||||
# is_shot = doc.xpath('boolean(//div[@id="shotgunMainResults"])')
|
||||
# # Horizontal grid of books.
|
||||
# if is_shot:
|
||||
# data_xpath = '//div[contains(@class, "result")]'
|
||||
# format_xpath = './/div[@class="productTitle"]/text()'
|
||||
# cover_xpath = './/div[@class="productTitle"]//img/@src'
|
||||
# # Vertical list of books.
|
||||
# else:
|
||||
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
|
||||
format_xpath = './/span[@class="format"]/text()'
|
||||
cover_xpath = './/img[@class="productImage"]/@src'
|
||||
# end is_shot else
|
||||
|
||||
for data in doc.xpath(data_xpath):
|
||||
if counter <= 0:
|
||||
break
|
||||
|
||||
# Even though we are searching digital-text only Amazon will still
|
||||
# put in results for non Kindle books (author pages). So we need
|
||||
# to explicitly check if the item is a Kindle book and ignore it
|
||||
# if it isn't.
|
||||
format = ''.join(data.xpath(format_xpath))
|
||||
if 'kindle' not in format.lower():
|
||||
continue
|
||||
|
||||
# We must have an asin otherwise we can't easily reference the
|
||||
# book later.
|
||||
asin = ''.join(data.xpath('./@name'))
|
||||
if not asin:
|
||||
continue
|
||||
asin = ''.join(data.xpath("@name"))
|
||||
|
||||
cover_url = ''.join(data.xpath(cover_xpath))
|
||||
|
||||
title = ''.join(data.xpath('.//div[@class="productTitle"]/a/text()'))
|
||||
title = ''.join(data.xpath('.//div[@class="title"]/a/text()'))
|
||||
price = ''.join(data.xpath('.//div[@class="newPrice"]/span/text()'))
|
||||
|
||||
# if is_shot:
|
||||
# author = format.split(' von ')[-1]
|
||||
# else:
|
||||
author = ''.join(data.xpath('.//div[@class="title"]/span[@class="ptBrand"]/text()'))
|
||||
author = author.split('by ')[-1]
|
||||
|
||||
counter -= 1
|
||||
|
||||
s = SearchResult()
|
||||
s.cover_url = cover_url.strip()
|
||||
s.title = title.strip()
|
||||
s.author = author.strip()
|
||||
s.price = price.strip()
|
||||
s.detail_item = asin.strip()
|
||||
s.formats = ''
|
||||
|
||||
if is_shot:
|
||||
# Amazon UK does not include the author on the grid layout
|
||||
s.author = ''
|
||||
self.get_details(s, timeout)
|
||||
if s.formats != 'Kindle':
|
||||
continue
|
||||
else:
|
||||
author = ''.join(data.xpath('.//div[@class="productTitle"]/span[@class="ptBrand"]/text()'))
|
||||
s.author = author.split(' by ')[-1].strip()
|
||||
s.formats = 'Kindle'
|
||||
s.formats = 'Kindle'
|
||||
|
||||
yield s
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||
|
||||
__license__ = 'GPL 3'
|
||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||
from calibre.gui2.store.opensearch_store import OpenSearchOPDSStore
|
||||
from calibre.gui2.store.search_result import SearchResult
|
||||
|
||||
class EpubBudStore(BasicStoreConfig, OpenSearchOPDSStore):
|
||||
|
||||
open_search_url = 'http://www.epubbud.com/feeds/opensearch.xml'
|
||||
web_url = 'http://www.epubbud.com/'
|
||||
|
||||
# http://www.epubbud.com/feeds/catalog.atom
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
for s in OpenSearchOPDSStore.search(self, query, max_results, timeout):
|
||||
s.price = '$0.00'
|
||||
s.drm = SearchResult.DRM_UNLOCKED
|
||||
s.formats = 'EPUB'
|
||||
# Download links are broken for this store.
|
||||
s.downloads = {}
|
||||
yield s
|
@ -1,80 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||
|
||||
__license__ = 'GPL 3'
|
||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import urllib2
|
||||
from contextlib import closing
|
||||
|
||||
from lxml import html
|
||||
|
||||
from PyQt4.Qt import QUrl
|
||||
|
||||
from calibre import browser
|
||||
from calibre.gui2 import open_url
|
||||
from calibre.gui2.store import StorePlugin
|
||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||
from calibre.gui2.store.search_result import SearchResult
|
||||
from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
|
||||
class EPubBuyDEStore(BasicStoreConfig, StorePlugin):
|
||||
|
||||
def open(self, parent=None, detail_item=None, external=False):
|
||||
url = 'http://klick.affiliwelt.net/klick.php?bannerid=47653&pid=32307&prid=2627'
|
||||
url_details = ('http://klick.affiliwelt.net/klick.php?bannerid=47653'
|
||||
'&pid=32307&prid=2627&prodid={0}')
|
||||
|
||||
if external or self.config.get('open_external', False):
|
||||
if detail_item:
|
||||
url = url_details.format(detail_item)
|
||||
open_url(QUrl(url))
|
||||
else:
|
||||
detail_url = None
|
||||
if detail_item:
|
||||
detail_url = url_details.format(detail_item)
|
||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||
d.setWindowTitle(self.name)
|
||||
d.set_tags(self.config.get('tags', ''))
|
||||
d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
url = 'http://www.epubbuy.com/search.php?search_query=' + urllib2.quote(query)
|
||||
br = browser()
|
||||
|
||||
counter = max_results
|
||||
with closing(br.open(url, timeout=timeout)) as f:
|
||||
doc = html.fromstring(f.read())
|
||||
for data in doc.xpath('//li[contains(@class, "ajax_block_product")]'):
|
||||
if counter <= 0:
|
||||
break
|
||||
|
||||
id = ''.join(data.xpath('./div[@class="center_block"]'
|
||||
'/p[contains(text(), "artnr:")]/text()')).strip()
|
||||
if not id:
|
||||
continue
|
||||
id = id[6:].strip()
|
||||
if not id:
|
||||
continue
|
||||
cover_url = ''.join(data.xpath('./div[@class="center_block"]'
|
||||
'/a[@class="product_img_link"]/img/@src'))
|
||||
if cover_url:
|
||||
cover_url = 'http://www.epubbuy.com' + cover_url
|
||||
title = ''.join(data.xpath('./div[@class="center_block"]'
|
||||
'/a[@class="product_img_link"]/@title'))
|
||||
author = ''.join(data.xpath('./div[@class="center_block"]/a[2]/text()'))
|
||||
price = ''.join(data.xpath('.//span[@class="price"]/text()'))
|
||||
counter -= 1
|
||||
|
||||
s = SearchResult()
|
||||
s.cover_url = cover_url
|
||||
s.title = title.strip()
|
||||
s.author = author.strip()
|
||||
s.price = price
|
||||
s.drm = SearchResult.DRM_UNLOCKED
|
||||
s.detail_item = id
|
||||
s.formats = 'ePub'
|
||||
|
||||
yield s
|
@ -6,6 +6,7 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import random
|
||||
import urllib
|
||||
from contextlib import closing
|
||||
|
||||
@ -23,7 +24,24 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
class GoogleBooksStore(BasicStoreConfig, StorePlugin):
|
||||
|
||||
def open(self, parent=None, detail_item=None, external=False):
|
||||
url = 'http://books.google.com/'
|
||||
aff_id = {
|
||||
'lid': '41000000033185143',
|
||||
'pubid': '21000000000352219',
|
||||
'ganpub': 'k352219',
|
||||
'ganclk': 'GOOG_1335334761',
|
||||
}
|
||||
# Use Kovid's affiliate id 30% of the time.
|
||||
if random.randint(1, 10) in (1, 2, 3):
|
||||
aff_id = {
|
||||
'lid': '41000000031855266',
|
||||
'pubid': '21000000000352583',
|
||||
'ganpub': 'k352583',
|
||||
'ganclk': 'GOOG_1335335464',
|
||||
}
|
||||
|
||||
url = 'http://gan.doubleclick.net/gan_click?lid=%(lid)s&pubid=%(pubid)s' % aff_id
|
||||
if detail_item:
|
||||
detail_item += '&ganpub=%(ganpub)s&ganclk=%(ganclk)s' % aff_id
|
||||
|
||||
if external or self.config.get('open_external', False):
|
||||
open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url)))
|
||||
|
126
src/calibre/gui2/store/stores/ozon_ru_plugin.py
Normal file
126
src/calibre/gui2/store/stores/ozon_ru_plugin.py
Normal file
@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||
|
||||
__license__ = 'GPL 3'
|
||||
__copyright__ = '2011, Roman Mukhin <ramses_ru at hotmail.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import random
|
||||
import re
|
||||
import urllib2
|
||||
|
||||
from contextlib import closing
|
||||
from lxml import etree, html
|
||||
from PyQt4.Qt import QUrl
|
||||
|
||||
from calibre import browser, url_slash_cleaner
|
||||
from calibre.ebooks.chardet import xml_to_unicode
|
||||
from calibre.gui2 import open_url
|
||||
from calibre.gui2.store import StorePlugin
|
||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||
from calibre.gui2.store.search_result import SearchResult
|
||||
from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
|
||||
class OzonRUStore(BasicStoreConfig, StorePlugin):
|
||||
shop_url = 'http://www.ozon.ru'
|
||||
|
||||
def open(self, parent=None, detail_item=None, external=False):
|
||||
|
||||
aff_id = '?partner=romuk'
|
||||
# Use Kovid's affiliate id 30% of the time.
|
||||
if random.randint(1, 10) in (1, 2, 3):
|
||||
aff_id = '?partner=kovidgoyal'
|
||||
|
||||
url = self.shop_url + aff_id
|
||||
detail_url = None
|
||||
if detail_item:
|
||||
# http://www.ozon.ru/context/detail/id/3037277/
|
||||
detail_url = self.shop_url + '/context/detail/id/' + urllib2.quote(detail_item) + aff_id
|
||||
|
||||
if external or self.config.get('open_external', False):
|
||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||
else:
|
||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||
d.setWindowTitle(self.name)
|
||||
d.set_tags(self.config.get('tags', ''))
|
||||
d.exec_()
|
||||
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
search_url = self.shop_url + '/webservice/webservice.asmx/SearchWebService?'\
|
||||
'searchText=%s&searchContext=ebook' % urllib2.quote(query)
|
||||
|
||||
counter = max_results
|
||||
br = browser()
|
||||
with closing(br.open(search_url, timeout=timeout)) as f:
|
||||
raw = xml_to_unicode(f.read(), strip_encoding_pats=True, assume_utf8=True)[0]
|
||||
doc = etree.fromstring(raw)
|
||||
for data in doc.xpath('//*[local-name() = "SearchItems"]'):
|
||||
if counter <= 0:
|
||||
break
|
||||
counter -= 1
|
||||
|
||||
xp_template = 'normalize-space(./*[local-name() = "{0}"]/text())'
|
||||
|
||||
s = SearchResult()
|
||||
s.detail_item = data.xpath(xp_template.format('ID'))
|
||||
s.title = data.xpath(xp_template.format('Name'))
|
||||
s.author = data.xpath(xp_template.format('Author'))
|
||||
s.price = data.xpath(xp_template.format('Price'))
|
||||
s.cover_url = data.xpath(xp_template.format('Picture'))
|
||||
if re.match("^\d+?\.\d+?$", s.price):
|
||||
s.price = u'{:.2F} руб.'.format(float(s.price))
|
||||
yield s
|
||||
|
||||
def get_details(self, search_result, timeout=60):
|
||||
url = self.shop_url + '/context/detail/id/' + urllib2.quote(search_result.detail_item)
|
||||
br = browser()
|
||||
|
||||
result = False
|
||||
with closing(br.open(url, timeout=timeout)) as f:
|
||||
doc = html.fromstring(f.read())
|
||||
|
||||
# example where we are going to find formats
|
||||
# <div class="box">
|
||||
# ...
|
||||
# <b>Доступные форматы:</b>
|
||||
# <div class="vertpadd">.epub, .fb2, .pdf, .pdf, .txt</div>
|
||||
# ...
|
||||
# </div>
|
||||
xpt = u'normalize-space(//div[@class="box"]//*[contains(normalize-space(text()), "Доступные форматы:")][1]/following-sibling::div[1]/text())'
|
||||
formats = doc.xpath(xpt)
|
||||
if formats:
|
||||
result = True
|
||||
search_result.drm = SearchResult.DRM_UNLOCKED
|
||||
search_result.formats = ', '.join(_parse_ebook_formats(formats))
|
||||
# unfortunately no direct links to download books (only buy link)
|
||||
# search_result.downloads['BF2'] = self.shop_url + '/order/digitalorder.aspx?id=' + + urllib2.quote(search_result.detail_item)
|
||||
return result
|
||||
|
||||
def _parse_ebook_formats(formatsStr):
|
||||
'''
|
||||
Creates a list with displayable names of the formats
|
||||
|
||||
:param formatsStr: string with comma separated book formats
|
||||
as it provided by ozon.ru
|
||||
:return: a list with displayable book formats
|
||||
'''
|
||||
|
||||
formatsUnstruct = formatsStr.lower()
|
||||
formats = []
|
||||
if 'epub' in formatsUnstruct:
|
||||
formats.append('ePub')
|
||||
if 'pdf' in formatsUnstruct:
|
||||
formats.append('PDF')
|
||||
if 'fb2' in formatsUnstruct:
|
||||
formats.append('FB2')
|
||||
if 'rtf' in formatsUnstruct:
|
||||
formats.append('RTF')
|
||||
if 'txt' in formatsUnstruct:
|
||||
formats.append('TXT')
|
||||
if 'djvu' in formatsUnstruct:
|
||||
formats.append('DjVu')
|
||||
if 'doc' in formatsUnstruct:
|
||||
formats.append('DOC')
|
||||
return formats
|
@ -5541,23 +5541,23 @@ msgstr "Книги с такими же тегами"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:20
|
||||
msgid "Get books"
|
||||
msgstr ""
|
||||
msgstr "Загрузить книги"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:29
|
||||
msgid "Search for ebooks"
|
||||
msgstr ""
|
||||
msgstr "Поиск книг..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:30
|
||||
msgid "Search for this author"
|
||||
msgstr ""
|
||||
msgstr "Поиск по автору"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:31
|
||||
msgid "Search for this title"
|
||||
msgstr ""
|
||||
msgstr "Поиск по названию"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:32
|
||||
msgid "Search for this book"
|
||||
msgstr ""
|
||||
msgstr "Поиск по книге"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:34
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:135
|
||||
@ -5569,21 +5569,21 @@ msgstr "Магазины"
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/chooser_dialog.py:18
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:285
|
||||
msgid "Choose stores"
|
||||
msgstr ""
|
||||
msgstr "Выбрать магазины"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:83
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:102
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:111
|
||||
msgid "Cannot search"
|
||||
msgstr ""
|
||||
msgstr "Поиск не может быть произведён"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:130
|
||||
msgid ""
|
||||
"Calibre helps you find the ebooks you want by searching the websites of "
|
||||
"various commercial and public domain book sources for you."
|
||||
msgstr ""
|
||||
"Calibre помогает вам отыскать книги, которые вы хотите найти, предлагая вам "
|
||||
"найденные веб-сайты различных коммерческих и публичных источников книг."
|
||||
"Calibre поможет Вам найти книги, предлагая "
|
||||
"веб-сайты различных коммерческих и публичных источников книг."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:134
|
||||
msgid ""
|
||||
@ -5591,6 +5591,8 @@ msgid ""
|
||||
"are looking for, at the best price. You also get DRM status and other useful "
|
||||
"information."
|
||||
msgstr ""
|
||||
"Используя встроенный поиск Вы можете легко найти магазин предлагающий выгодную цену "
|
||||
"для интересующей Вас книги. Также Вы получите другу полезную инфрмацию"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:138
|
||||
msgid ""
|
||||
@ -5608,7 +5610,7 @@ msgstr "Показать снова данное сообщение"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:149
|
||||
msgid "About Get Books"
|
||||
msgstr ""
|
||||
msgstr "О 'Загрузить книги'"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:17
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:60
|
||||
@ -5617,7 +5619,7 @@ msgstr "Tweak EPUB"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:18
|
||||
msgid "Make small changes to ePub format books"
|
||||
msgstr ""
|
||||
msgstr "Внести небольшие изненения ePub в формат книги"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:19
|
||||
msgid "T"
|
||||
@ -5704,7 +5706,7 @@ msgstr "Не могу открыть папку"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:220
|
||||
msgid "This book no longer exists in your library"
|
||||
msgstr ""
|
||||
msgstr "Эта книга больше не находится в Вашей библиотеке"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:227
|
||||
#, python-format
|
||||
@ -9167,11 +9169,11 @@ msgstr "&Показать пароль"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:122
|
||||
msgid "Restart required"
|
||||
msgstr ""
|
||||
msgstr "Требуется перезапуск"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:123
|
||||
msgid "You must restart Calibre before using this plugin!"
|
||||
msgstr ""
|
||||
msgstr "Для использования плагина Вам нужно перезапустить Calibre!"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:164
|
||||
#, python-format
|
||||
@ -9183,17 +9185,17 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:136
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search_ui.py:111
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
msgstr "Всё"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:184
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:302
|
||||
msgid "Installed"
|
||||
msgstr ""
|
||||
msgstr "Установленные"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:184
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:397
|
||||
msgid "Not installed"
|
||||
msgstr ""
|
||||
msgstr "Не установленные"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:184
|
||||
msgid "Update available"
|
||||
@ -9201,7 +9203,7 @@ msgstr "Доступно обновление"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:302
|
||||
msgid "Plugin Name"
|
||||
msgstr ""
|
||||
msgstr "Название плагина"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/plugin_updater.py:302
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/jobs.py:63
|
||||
@ -13317,7 +13319,7 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugins_ui.py:114
|
||||
msgid "&Load plugin from file"
|
||||
msgstr ""
|
||||
msgstr "Загрузить плагин из файла"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:33
|
||||
msgid "Any custom field"
|
||||
@ -13579,11 +13581,11 @@ msgstr "Сбой запуска контент-сервера"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:106
|
||||
msgid "Error log:"
|
||||
msgstr "Лог ошибок:"
|
||||
msgstr "Журнал ошибок:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:113
|
||||
msgid "Access log:"
|
||||
msgstr "Лог доступа:"
|
||||
msgstr "Журнал доступа:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:128
|
||||
msgid "You need to restart the server for changes to take effect"
|
||||
@ -14053,7 +14055,7 @@ msgstr "Ничего"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:59
|
||||
msgid "Press a key..."
|
||||
msgstr ""
|
||||
msgstr "Нажмите клавишу..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:80
|
||||
msgid "Already assigned"
|
||||
@ -14108,19 +14110,19 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/basic_config_widget_ui.py:38
|
||||
msgid "Added Tags:"
|
||||
msgstr ""
|
||||
msgstr "Добавленные тэги:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/basic_config_widget_ui.py:39
|
||||
msgid "Open store in external web browswer"
|
||||
msgstr ""
|
||||
msgstr "Открыть сайт магазина в интернет броузере"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:219
|
||||
msgid "&Name:"
|
||||
msgstr ""
|
||||
msgstr "&Название"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:221
|
||||
msgid "&Description:"
|
||||
msgstr ""
|
||||
msgstr "&Описание"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:222
|
||||
msgid "&Headquarters:"
|
||||
@ -14140,7 +14142,7 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:217
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:220
|
||||
msgid "true"
|
||||
msgstr ""
|
||||
msgstr "да"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:229
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:231
|
||||
@ -14148,41 +14150,41 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:218
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:221
|
||||
msgid "false"
|
||||
msgstr ""
|
||||
msgstr "нет"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:232
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:216
|
||||
msgid "Affiliate:"
|
||||
msgstr ""
|
||||
msgstr "Партнёрство:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/adv_search_builder_ui.py:235
|
||||
msgid "Nam&e/Description ..."
|
||||
msgstr ""
|
||||
msgstr "Названи&е/Описание"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/chooser_widget_ui.py:78
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:132
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search_ui.py:108
|
||||
msgid "Query:"
|
||||
msgstr ""
|
||||
msgstr "Запрос:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/chooser_widget_ui.py:81
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
msgstr "Включить"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/chooser_widget_ui.py:84
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:137
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search_ui.py:112
|
||||
msgid "Invert"
|
||||
msgstr ""
|
||||
msgstr "Инвертировать"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:21
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:37
|
||||
msgid "Affiliate"
|
||||
msgstr ""
|
||||
msgstr "Партнерство"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:21
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
msgstr "Включено"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:21
|
||||
msgid "Headquarters"
|
||||
@ -14190,7 +14192,7 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:21
|
||||
msgid "No DRM"
|
||||
msgstr ""
|
||||
msgstr "Без DRM"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:129
|
||||
msgid ""
|
||||
@ -14205,13 +14207,14 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:136
|
||||
msgid "This store only distributes ebooks without DRM."
|
||||
msgstr ""
|
||||
msgstr "Этот магазин распространяет электронные книги исключительно без DRM"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:138
|
||||
msgid ""
|
||||
"This store distributes ebooks with DRM. It may have some titles without DRM, "
|
||||
"but you will need to check on a per title basis."
|
||||
msgstr ""
|
||||
msgstr "Этот магазин распространяет электронные книги с DRM. Возможно, некоторые издания"
|
||||
" доступны без DRM, но для этого надо проверять каждую книгу в отдельности."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:140
|
||||
#, python-format
|
||||
@ -14225,46 +14228,46 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:211
|
||||
#, python-format
|
||||
msgid "Buying from this store supports the calibre developer: %s."
|
||||
msgstr ""
|
||||
msgstr "Покупая в этом магазине Вы поддерживаете проект calibre и разработчика: %s."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/models.py:145
|
||||
#, python-format
|
||||
msgid "This store distributes ebooks in the following formats: %s"
|
||||
msgstr ""
|
||||
msgstr "Магазин распространяет эл. книги в следующих фотрматах"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/chooser/results_view.py:47
|
||||
msgid "Configure..."
|
||||
msgstr ""
|
||||
msgstr "Настроить..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:99
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:99
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
msgstr "Время"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:100
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:100
|
||||
msgid "Number of seconds to wait for a store to respond"
|
||||
msgstr ""
|
||||
msgstr "Время ожидания ответа магазина (в секундах)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:101
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:101
|
||||
msgid "Number of seconds to let a store process results"
|
||||
msgstr ""
|
||||
msgstr "Допустипое время обработки результата магазином (в секундах)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:102
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:102
|
||||
msgid "Display"
|
||||
msgstr ""
|
||||
msgstr "Показать"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:103
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:103
|
||||
msgid "Maximum number of results to show per store"
|
||||
msgstr ""
|
||||
msgstr "Максимальное количество результатов для показа (по каждому магазину)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:104
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:104
|
||||
msgid "Open search result in system browser"
|
||||
msgstr ""
|
||||
msgstr "Показывать результаты поиска в системном интернет броузере"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search/search_widget_ui.py:105
|
||||
msgid "Threads"
|
||||
@ -14288,11 +14291,11 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:105
|
||||
msgid "Performance"
|
||||
msgstr ""
|
||||
msgstr "Производительность"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:106
|
||||
msgid "Number of simultaneous searches"
|
||||
msgstr ""
|
||||
msgstr "Количество одновременно выполняемых поисков"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/config/search_widget_ui.py:107
|
||||
msgid "Number of simultaneous cache updates"
|
||||
@ -14308,13 +14311,13 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/mobileread_store_dialog_ui.py:62
|
||||
msgid "Search:"
|
||||
msgstr ""
|
||||
msgstr "Поиск:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/mobileread_store_dialog_ui.py:63
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:142
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/store_dialog_ui.py:77
|
||||
msgid "Books:"
|
||||
msgstr ""
|
||||
msgstr "Книги:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/mobileread_store_dialog_ui.py:65
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:144
|
||||
@ -14323,20 +14326,20 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_store_dialog_ui.py:63
|
||||
#: /usr/src/qt-everywhere-opensource-src-4.7.2/src/gui/widgets/qdialogbuttonbox.cpp:661
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
msgstr "Закрыть"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:212
|
||||
msgid "&Price:"
|
||||
msgstr ""
|
||||
msgstr "&Цена:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:219
|
||||
msgid "Download:"
|
||||
msgstr ""
|
||||
msgstr "Скачать"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/adv_search_builder_ui.py:222
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/adv_search_builder_ui.py:187
|
||||
msgid "Titl&e/Author/Price ..."
|
||||
msgstr ""
|
||||
msgstr "Названи&е/Автор/Цена ..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:37
|
||||
msgid "DRM"
|
||||
@ -14344,11 +14347,11 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:37
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
msgstr "Скачать"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:37
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Цена"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:196
|
||||
#, python-format
|
||||
@ -14383,90 +14386,90 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:208
|
||||
#, python-format
|
||||
msgid "The following formats can be downloaded directly: %s."
|
||||
msgstr ""
|
||||
msgstr "Форматы доступные для непосредственного скачивания: %s."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/results_view.py:41
|
||||
msgid "Download..."
|
||||
msgstr ""
|
||||
msgstr "Скачать..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/results_view.py:45
|
||||
msgid "Goto in store..."
|
||||
msgstr ""
|
||||
msgstr "Перейти в магазин..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:114
|
||||
#, python-format
|
||||
msgid "Buying from this store supports the calibre developer: %s</p>"
|
||||
msgstr ""
|
||||
msgstr "Покупая в этом магазине Вы поддерживаете проект calibre и разработчика: %s</p>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:276
|
||||
msgid "Customize get books search"
|
||||
msgstr ""
|
||||
msgstr "Перенастроить под себя поиск книг для скачивания"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:286
|
||||
msgid "Configure search"
|
||||
msgstr ""
|
||||
msgstr "Настроить поиск"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:336
|
||||
msgid "Couldn't find any books matching your query."
|
||||
msgstr "Ну удалось найти ни одной кники, соотвествующей вашему запросу."
|
||||
msgstr "Не удалось найти ни одной книги, соотвествующей вашему запросу."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search.py:350
|
||||
msgid "Choose format to download to your library."
|
||||
msgstr ""
|
||||
msgstr "Выберите формат для скачивания в библиотеку"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:131
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search_ui.py:107
|
||||
msgid "Get Books"
|
||||
msgstr ""
|
||||
msgstr "Скачать книги"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:140
|
||||
msgid "Open a selected book in the system's web browser"
|
||||
msgstr ""
|
||||
msgstr "Показать выбранную книгу в системном интернет броузере"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/search_ui.py:141
|
||||
msgid "Open in &external browser"
|
||||
msgstr ""
|
||||
msgstr "Показывать в системном интернет броузере"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/ebooks_com_plugin.py:96
|
||||
msgid "Not Available"
|
||||
msgstr ""
|
||||
msgstr "Недоступно"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/adv_search_builder_ui.py:179
|
||||
msgid ""
|
||||
"See the <a href=\"http://calibre-ebook.com/user_manual/gui.html#the-search-"
|
||||
"interface\">User Manual</a> for more help"
|
||||
msgstr ""
|
||||
"Смотри <a href=\"http://calibre-ebook.com/user_manual/gui.html#the-search-"
|
||||
"interface\">Пользовательский мануал</a> для помощи"
|
||||
"Смотрите <a href=\"http://calibre-ebook.com/user_manual/gui.html#the-search-"
|
||||
"interface\">Руководство пользователя</a> для помощи"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/cache_progress_dialog_ui.py:51
|
||||
msgid "Updating book cache"
|
||||
msgstr ""
|
||||
msgstr "Обноволяется кэш книг"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/cache_update_thread.py:42
|
||||
msgid "Checking last download date."
|
||||
msgstr ""
|
||||
msgstr "Проверяется врема последнего скачивания"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/cache_update_thread.py:48
|
||||
msgid "Downloading book list from MobileRead."
|
||||
msgstr ""
|
||||
msgstr "Загружается список книг с MobileRead."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/cache_update_thread.py:61
|
||||
msgid "Processing books."
|
||||
msgstr ""
|
||||
msgstr "Книги обрабатываются"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/cache_update_thread.py:71
|
||||
#, python-format
|
||||
msgid "%(num)s of %(tot)s books processed."
|
||||
msgstr ""
|
||||
msgstr "обработано %(num)s из %(tot)."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/mobileread_plugin.py:62
|
||||
msgid "Updating MobileRead book cache..."
|
||||
msgstr ""
|
||||
msgstr "Обноволяется кэщ MobileRead книг..."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/stores/mobileread/store_dialog_ui.py:74
|
||||
msgid "&Query:"
|
||||
msgstr ""
|
||||
msgstr "&Запрос:"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_control.py:73
|
||||
msgid ""
|
||||
@ -14480,15 +14483,15 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_control.py:86
|
||||
msgid "File is not a supported ebook type. Save to disk?"
|
||||
msgstr ""
|
||||
msgstr "Файл содержит неподдерживаемый формат эл. книги. Сохранить на диске?"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_store_dialog_ui.py:59
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
msgstr "Главная страница"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_store_dialog_ui.py:60
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
msgstr "Перегрузить"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/store/web_store_dialog_ui.py:61
|
||||
msgid "%p%"
|
||||
@ -14502,22 +14505,24 @@ msgstr ""
|
||||
msgid ""
|
||||
"Changing the authors for several books can take a while. Are you sure?"
|
||||
msgstr ""
|
||||
"Изменить автора нескольких книг займёт некоторое время. Вы согласны"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:729
|
||||
msgid ""
|
||||
"Changing the metadata for that many books can take a while. Are you sure?"
|
||||
msgstr ""
|
||||
"Изменить мета-данные нескольких книг займёт некоторое время. Вы согласны"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:816
|
||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:449
|
||||
msgid "Searches"
|
||||
msgstr ""
|
||||
msgstr "Поиски"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:881
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:901
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:910
|
||||
msgid "Rename user category"
|
||||
msgstr ""
|
||||
msgstr "Переименовать пользовательскую категорию"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:882
|
||||
msgid "You cannot use periods in the name when renaming user categories"
|
||||
@ -14540,30 +14545,30 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:48
|
||||
msgid "Manage Authors"
|
||||
msgstr ""
|
||||
msgstr "Упорядочнить авторов"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:50
|
||||
msgid "Manage Series"
|
||||
msgstr ""
|
||||
msgstr "Упорядочнить серии"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:52
|
||||
msgid "Manage Publishers"
|
||||
msgstr ""
|
||||
msgstr "Упорядочнить издателей"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:54
|
||||
msgid "Manage Tags"
|
||||
msgstr ""
|
||||
msgstr "Упорядочнить тэги"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:56
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:465
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:469
|
||||
msgid "Manage User Categories"
|
||||
msgstr "Управление пользовательскими категориями"
|
||||
msgstr "Упорядочнить пользовательские категории"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:58
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:457
|
||||
msgid "Manage Saved Searches"
|
||||
msgstr "Управление сохраненными поисками"
|
||||
msgstr "Упорядочнить сохраненные поиски"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:66
|
||||
msgid "Invalid search restriction"
|
||||
@ -14580,17 +14585,17 @@ msgstr "Новая категория"
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:134
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:137
|
||||
msgid "Delete user category"
|
||||
msgstr ""
|
||||
msgstr "Удалить пользовательскую категорию"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:135
|
||||
#, python-format
|
||||
msgid "%s is not a user category"
|
||||
msgstr ""
|
||||
msgstr "%s не является пользовательской категорией"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:138
|
||||
#, python-format
|
||||
msgid "%s contains items. Do you really want to delete it?"
|
||||
msgstr ""
|
||||
msgstr "%s содержит элементы. Вы действительно хотете её удалить?"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:159
|
||||
msgid "Remove category"
|
||||
@ -14599,16 +14604,16 @@ msgstr "Удалить категорию"
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:160
|
||||
#, python-format
|
||||
msgid "User category %s does not exist"
|
||||
msgstr ""
|
||||
msgstr "Пользовательская категория %s не существует"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:179
|
||||
msgid "Add to user category"
|
||||
msgstr ""
|
||||
msgstr "Добавить в пользовательские категории"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:180
|
||||
#, python-format
|
||||
msgid "A user category %s does not exist"
|
||||
msgstr ""
|
||||
msgstr "Пользовательская категория %s не существует"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:305
|
||||
msgid "Find item in tag browser"
|
||||
@ -14701,7 +14706,7 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:359
|
||||
#, python-format
|
||||
msgid "Add %s to user category"
|
||||
msgstr ""
|
||||
msgstr "Добавить %s в пользовательские категории"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:372
|
||||
#, python-format
|
||||
@ -14711,7 +14716,7 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:382
|
||||
#, python-format
|
||||
msgid "Delete search %s"
|
||||
msgstr ""
|
||||
msgstr "Удалить поиск %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:387
|
||||
#, python-format
|
||||
@ -14721,27 +14726,27 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:394
|
||||
#, python-format
|
||||
msgid "Search for %s"
|
||||
msgstr ""
|
||||
msgstr "Искать %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:399
|
||||
#, python-format
|
||||
msgid "Search for everything but %s"
|
||||
msgstr ""
|
||||
msgstr "Искать всё кроме %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:411
|
||||
#, python-format
|
||||
msgid "Add sub-category to %s"
|
||||
msgstr ""
|
||||
msgstr "Добавить подкатегорию в %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:415
|
||||
#, python-format
|
||||
msgid "Delete user category %s"
|
||||
msgstr ""
|
||||
msgstr "Удалить пользовательскую категорию %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:420
|
||||
#, python-format
|
||||
msgid "Hide category %s"
|
||||
msgstr ""
|
||||
msgstr "Скрыть категорию %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:424
|
||||
msgid "Show category"
|
||||
@ -14750,12 +14755,12 @@ msgstr "Показать категорию"
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:434
|
||||
#, python-format
|
||||
msgid "Search for books in category %s"
|
||||
msgstr ""
|
||||
msgstr "Искать книги в категории %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:440
|
||||
#, python-format
|
||||
msgid "Search for books not in category %s"
|
||||
msgstr ""
|
||||
msgstr "Искать книги НЕ в категории %s"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:449
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:454
|
||||
@ -14837,7 +14842,7 @@ msgstr "Извлечь подключенное устройство"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:347
|
||||
msgid "Debug mode"
|
||||
msgstr ""
|
||||
msgstr "Резим отладки"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:348
|
||||
#, python-format
|
||||
@ -14875,7 +14880,7 @@ msgstr ""
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:630
|
||||
msgid "Active jobs"
|
||||
msgstr ""
|
||||
msgstr "Активные задания"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:698
|
||||
msgid ""
|
||||
@ -14898,11 +14903,11 @@ msgstr "Доступно обновление!"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/update.py:84
|
||||
msgid "Show this notification for future updates"
|
||||
msgstr ""
|
||||
msgstr "Показвать сообщение о доступности новой версии (обнивления)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/update.py:89
|
||||
msgid "&Get update"
|
||||
msgstr ""
|
||||
msgstr "&Скачать обнивление"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/update.py:93
|
||||
msgid "Update &plugins"
|
||||
@ -14929,11 +14934,11 @@ msgstr ""
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/update.py:187
|
||||
#, python-format
|
||||
msgid "There are %d plugin updates available"
|
||||
msgstr ""
|
||||
msgstr "Доступны обновления для %d плагинов"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/update.py:191
|
||||
msgid "Install and configure user plugins"
|
||||
msgstr ""
|
||||
msgstr "Установка и настройка пользовательских плагинов"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/bookmarkmanager.py:43
|
||||
msgid "Edit bookmark"
|
||||
|
Loading…
x
Reference in New Issue
Block a user