mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-01-07 07:45:28 +00:00
Merge branch 'main' into production
This commit is contained in:
commit
8761357905
74 changed files with 2195 additions and 661 deletions
|
@ -7,6 +7,9 @@ DEBUG=false
|
||||||
DOMAIN=your.domain.here
|
DOMAIN=your.domain.here
|
||||||
#EMAIL=your@email.here
|
#EMAIL=your@email.here
|
||||||
|
|
||||||
|
# Used for deciding which editions to prefer
|
||||||
|
DEFAULT_LANGUAGE="English"
|
||||||
|
|
||||||
## Leave unset to allow all hosts
|
## Leave unset to allow all hosts
|
||||||
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ DEBUG=false
|
||||||
DOMAIN=your.domain.here
|
DOMAIN=your.domain.here
|
||||||
EMAIL=your@email.here
|
EMAIL=your@email.here
|
||||||
|
|
||||||
|
# Used for deciding which editions to prefer
|
||||||
|
DEFAULT_LANGUAGE="English"
|
||||||
|
|
||||||
## Leave unset to allow all hosts
|
## Leave unset to allow all hosts
|
||||||
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,11 @@ Permission is hereby granted, free of charge, to any person or organization (the
|
||||||
1. The above copyright notice and this permission notice shall be included in all copies or modified versions of the Software.
|
1. The above copyright notice and this permission notice shall be included in all copies or modified versions of the Software.
|
||||||
|
|
||||||
2. The User is one of the following:
|
2. The User is one of the following:
|
||||||
a. An individual person, laboring for themselves
|
|
||||||
b. A non-profit organization
|
1. An individual person, laboring for themselves
|
||||||
c. An educational institution
|
2. A non-profit organization
|
||||||
d. An organization that seeks shared profit for all of its members, and allows non-members to set the cost of their labor
|
3. An educational institution
|
||||||
|
4. An organization that seeks shared profit for all of its members, and allows non-members to set the cost of their labor
|
||||||
|
|
||||||
3. If the User is an organization with owners, then all owners are workers and all workers are owners with equal equity and/or equal vote.
|
3. If the User is an organization with owners, then all owners are workers and all workers are owners with equal equity and/or equal vote.
|
||||||
|
|
|
@ -7,11 +7,22 @@ from .image import Document
|
||||||
|
|
||||||
|
|
||||||
@dataclass(init=False)
|
@dataclass(init=False)
|
||||||
class Book(ActivityObject):
|
class BookData(ActivityObject):
|
||||||
|
"""shared fields for all book data and authors"""
|
||||||
|
|
||||||
|
openlibraryKey: str = None
|
||||||
|
inventaireId: str = None
|
||||||
|
librarythingKey: str = None
|
||||||
|
goodreadsKey: str = None
|
||||||
|
bnfId: str = None
|
||||||
|
lastEditedBy: str = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(init=False)
|
||||||
|
class Book(BookData):
|
||||||
"""serializes an edition or work, abstract"""
|
"""serializes an edition or work, abstract"""
|
||||||
|
|
||||||
title: str
|
title: str
|
||||||
lastEditedBy: str = None
|
|
||||||
sortTitle: str = ""
|
sortTitle: str = ""
|
||||||
subtitle: str = ""
|
subtitle: str = ""
|
||||||
description: str = ""
|
description: str = ""
|
||||||
|
@ -25,10 +36,6 @@ class Book(ActivityObject):
|
||||||
firstPublishedDate: str = ""
|
firstPublishedDate: str = ""
|
||||||
publishedDate: str = ""
|
publishedDate: str = ""
|
||||||
|
|
||||||
openlibraryKey: str = ""
|
|
||||||
librarythingKey: str = ""
|
|
||||||
goodreadsKey: str = ""
|
|
||||||
|
|
||||||
cover: Document = None
|
cover: Document = None
|
||||||
type: str = "Book"
|
type: str = "Book"
|
||||||
|
|
||||||
|
@ -55,23 +62,21 @@ class Work(Book):
|
||||||
"""work instance of a book object"""
|
"""work instance of a book object"""
|
||||||
|
|
||||||
lccn: str = ""
|
lccn: str = ""
|
||||||
defaultEdition: str = ""
|
|
||||||
editions: List[str] = field(default_factory=lambda: [])
|
editions: List[str] = field(default_factory=lambda: [])
|
||||||
type: str = "Work"
|
type: str = "Work"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(init=False)
|
@dataclass(init=False)
|
||||||
class Author(ActivityObject):
|
class Author(BookData):
|
||||||
"""author of a book"""
|
"""author of a book"""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
lastEditedBy: str = None
|
isni: str = None
|
||||||
|
viafId: str = None
|
||||||
|
gutenbergId: str = None
|
||||||
born: str = None
|
born: str = None
|
||||||
died: str = None
|
died: str = None
|
||||||
aliases: List[str] = field(default_factory=lambda: [])
|
aliases: List[str] = field(default_factory=lambda: [])
|
||||||
bio: str = ""
|
bio: str = ""
|
||||||
openlibraryKey: str = ""
|
|
||||||
librarythingKey: str = ""
|
|
||||||
goodreadsKey: str = ""
|
|
||||||
wikipediaLink: str = ""
|
wikipediaLink: str = ""
|
||||||
type: str = "Author"
|
type: str = "Author"
|
||||||
|
|
|
@ -83,4 +83,5 @@ class Rating(Comment):
|
||||||
|
|
||||||
rating: int
|
rating: int
|
||||||
content: str = None
|
content: str = None
|
||||||
|
name: str = None # not used, but the model inherits from Review
|
||||||
type: str = "Rating"
|
type: str = "Rating"
|
||||||
|
|
|
@ -44,7 +44,7 @@ class AbstractMinimalConnector(ABC):
|
||||||
if min_confidence:
|
if min_confidence:
|
||||||
params["min_confidence"] = min_confidence
|
params["min_confidence"] = min_confidence
|
||||||
|
|
||||||
data = get_data(
|
data = self.get_search_data(
|
||||||
"%s%s" % (self.search_url, query),
|
"%s%s" % (self.search_url, query),
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
|
@ -57,7 +57,7 @@ class AbstractMinimalConnector(ABC):
|
||||||
def isbn_search(self, query):
|
def isbn_search(self, query):
|
||||||
"""isbn search"""
|
"""isbn search"""
|
||||||
params = {}
|
params = {}
|
||||||
data = get_data(
|
data = self.get_search_data(
|
||||||
"%s%s" % (self.isbn_search_url, query),
|
"%s%s" % (self.isbn_search_url, query),
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
|
@ -68,6 +68,10 @@ class AbstractMinimalConnector(ABC):
|
||||||
results.append(self.format_isbn_search_result(doc))
|
results.append(self.format_isbn_search_result(doc))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def get_search_data(self, remote_id, **kwargs): # pylint: disable=no-self-use
|
||||||
|
"""this allows connectors to override the default behavior"""
|
||||||
|
return get_data(remote_id, **kwargs)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_or_create_book(self, remote_id):
|
def get_or_create_book(self, remote_id):
|
||||||
"""pull up a book record by whatever means possible"""
|
"""pull up a book record by whatever means possible"""
|
||||||
|
@ -112,12 +116,12 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
remote_id
|
remote_id
|
||||||
) or models.Work.find_existing_by_remote_id(remote_id)
|
) or models.Work.find_existing_by_remote_id(remote_id)
|
||||||
if existing:
|
if existing:
|
||||||
if hasattr(existing, "get_default_editon"):
|
if hasattr(existing, "default_edition"):
|
||||||
return existing.get_default_editon()
|
return existing.default_edition
|
||||||
return existing
|
return existing
|
||||||
|
|
||||||
# load the json
|
# load the json
|
||||||
data = get_data(remote_id)
|
data = self.get_book_data(remote_id)
|
||||||
mapped_data = dict_from_mappings(data, self.book_mappings)
|
mapped_data = dict_from_mappings(data, self.book_mappings)
|
||||||
if self.is_work_data(data):
|
if self.is_work_data(data):
|
||||||
try:
|
try:
|
||||||
|
@ -128,12 +132,12 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
edition_data = data
|
edition_data = data
|
||||||
work_data = mapped_data
|
work_data = mapped_data
|
||||||
else:
|
else:
|
||||||
|
edition_data = data
|
||||||
try:
|
try:
|
||||||
work_data = self.get_work_from_edition_data(data)
|
work_data = self.get_work_from_edition_data(data)
|
||||||
work_data = dict_from_mappings(work_data, self.book_mappings)
|
work_data = dict_from_mappings(work_data, self.book_mappings)
|
||||||
except (KeyError, ConnectorException):
|
except (KeyError, ConnectorException):
|
||||||
work_data = mapped_data
|
work_data = mapped_data
|
||||||
edition_data = data
|
|
||||||
|
|
||||||
if not work_data or not edition_data:
|
if not work_data or not edition_data:
|
||||||
raise ConnectorException("Unable to load book data: %s" % remote_id)
|
raise ConnectorException("Unable to load book data: %s" % remote_id)
|
||||||
|
@ -150,6 +154,10 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
load_more_data.delay(self.connector.id, work.id)
|
load_more_data.delay(self.connector.id, work.id)
|
||||||
return edition
|
return edition
|
||||||
|
|
||||||
|
def get_book_data(self, remote_id): # pylint: disable=no-self-use
|
||||||
|
"""this allows connectors to override the default behavior"""
|
||||||
|
return get_data(remote_id)
|
||||||
|
|
||||||
def create_edition_from_data(self, work, edition_data):
|
def create_edition_from_data(self, work, edition_data):
|
||||||
"""if we already have the work, we're ready"""
|
"""if we already have the work, we're ready"""
|
||||||
mapped_data = dict_from_mappings(edition_data, self.book_mappings)
|
mapped_data = dict_from_mappings(edition_data, self.book_mappings)
|
||||||
|
@ -159,10 +167,6 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
edition.connector = self.connector
|
edition.connector = self.connector
|
||||||
edition.save()
|
edition.save()
|
||||||
|
|
||||||
if not work.default_edition:
|
|
||||||
work.default_edition = edition
|
|
||||||
work.save()
|
|
||||||
|
|
||||||
for author in self.get_authors_from_data(edition_data):
|
for author in self.get_authors_from_data(edition_data):
|
||||||
edition.authors.add(author)
|
edition.authors.add(author)
|
||||||
if not edition.authors.exists() and work.authors.exists():
|
if not edition.authors.exists() and work.authors.exists():
|
||||||
|
@ -176,7 +180,7 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
if existing:
|
if existing:
|
||||||
return existing
|
return existing
|
||||||
|
|
||||||
data = get_data(remote_id)
|
data = self.get_book_data(remote_id)
|
||||||
|
|
||||||
mapped_data = dict_from_mappings(data, self.author_mappings)
|
mapped_data = dict_from_mappings(data, self.author_mappings)
|
||||||
try:
|
try:
|
||||||
|
@ -273,6 +277,7 @@ class SearchResult:
|
||||||
title: str
|
title: str
|
||||||
key: str
|
key: str
|
||||||
connector: object
|
connector: object
|
||||||
|
view_link: str = None
|
||||||
author: str = None
|
author: str = None
|
||||||
year: str = None
|
year: str = None
|
||||||
cover: str = None
|
cover: str = None
|
||||||
|
|
|
@ -7,11 +7,7 @@ class Connector(AbstractMinimalConnector):
|
||||||
"""this is basically just for search"""
|
"""this is basically just for search"""
|
||||||
|
|
||||||
def get_or_create_book(self, remote_id):
|
def get_or_create_book(self, remote_id):
|
||||||
edition = activitypub.resolve_remote_id(remote_id, model=models.Edition)
|
return activitypub.resolve_remote_id(remote_id, model=models.Edition)
|
||||||
work = edition.parent_work
|
|
||||||
work.default_edition = work.get_default_edition()
|
|
||||||
work.save()
|
|
||||||
return edition
|
|
||||||
|
|
||||||
def parse_search_data(self, data):
|
def parse_search_data(self, data):
|
||||||
return data
|
return data
|
||||||
|
|
214
bookwyrm/connectors/inventaire.py
Normal file
214
bookwyrm/connectors/inventaire.py
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
""" inventaire data connector """
|
||||||
|
import re
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from .abstract_connector import AbstractConnector, SearchResult, Mapping
|
||||||
|
from .abstract_connector import get_data
|
||||||
|
from .connector_manager import ConnectorException
|
||||||
|
|
||||||
|
|
||||||
|
class Connector(AbstractConnector):
|
||||||
|
"""instantiate a connector for OL"""
|
||||||
|
|
||||||
|
def __init__(self, identifier):
|
||||||
|
super().__init__(identifier)
|
||||||
|
|
||||||
|
get_first = lambda a: a[0]
|
||||||
|
shared_mappings = [
|
||||||
|
Mapping("id", remote_field="uri", formatter=self.get_remote_id),
|
||||||
|
Mapping("bnfId", remote_field="wdt:P268", formatter=get_first),
|
||||||
|
Mapping("openlibraryKey", remote_field="wdt:P648", formatter=get_first),
|
||||||
|
]
|
||||||
|
self.book_mappings = [
|
||||||
|
Mapping("title", remote_field="wdt:P1476", formatter=get_first),
|
||||||
|
Mapping("subtitle", remote_field="wdt:P1680", formatter=get_first),
|
||||||
|
Mapping("inventaireId", remote_field="uri"),
|
||||||
|
Mapping(
|
||||||
|
"description", remote_field="sitelinks", formatter=self.get_description
|
||||||
|
),
|
||||||
|
Mapping("cover", remote_field="image", formatter=self.get_cover_url),
|
||||||
|
Mapping("isbn13", remote_field="wdt:P212", formatter=get_first),
|
||||||
|
Mapping("isbn10", remote_field="wdt:P957", formatter=get_first),
|
||||||
|
Mapping("oclcNumber", remote_field="wdt:P5331", formatter=get_first),
|
||||||
|
Mapping("goodreadsKey", remote_field="wdt:P2969", formatter=get_first),
|
||||||
|
Mapping("librarythingKey", remote_field="wdt:P1085", formatter=get_first),
|
||||||
|
Mapping("languages", remote_field="wdt:P407", formatter=self.resolve_keys),
|
||||||
|
Mapping("publishers", remote_field="wdt:P123", formatter=self.resolve_keys),
|
||||||
|
Mapping("publishedDate", remote_field="wdt:P577", formatter=get_first),
|
||||||
|
Mapping("pages", remote_field="wdt:P1104", formatter=get_first),
|
||||||
|
Mapping(
|
||||||
|
"subjectPlaces", remote_field="wdt:P840", formatter=self.resolve_keys
|
||||||
|
),
|
||||||
|
Mapping("subjects", remote_field="wdt:P921", formatter=self.resolve_keys),
|
||||||
|
Mapping("asin", remote_field="wdt:P5749", formatter=get_first),
|
||||||
|
] + shared_mappings
|
||||||
|
# TODO: P136: genre, P674 characters, P950 bne
|
||||||
|
|
||||||
|
self.author_mappings = [
|
||||||
|
Mapping("id", remote_field="uri", formatter=self.get_remote_id),
|
||||||
|
Mapping("name", remote_field="labels", formatter=get_language_code),
|
||||||
|
Mapping("bio", remote_field="sitelinks", formatter=self.get_description),
|
||||||
|
Mapping("goodreadsKey", remote_field="wdt:P2963", formatter=get_first),
|
||||||
|
Mapping("isni", remote_field="wdt:P213", formatter=get_first),
|
||||||
|
Mapping("viafId", remote_field="wdt:P214", formatter=get_first),
|
||||||
|
Mapping("gutenberg_id", remote_field="wdt:P1938", formatter=get_first),
|
||||||
|
Mapping("born", remote_field="wdt:P569", formatter=get_first),
|
||||||
|
Mapping("died", remote_field="wdt:P570", formatter=get_first),
|
||||||
|
] + shared_mappings
|
||||||
|
|
||||||
|
def get_remote_id(self, value):
|
||||||
|
"""convert an id/uri into a url"""
|
||||||
|
return "{:s}?action=by-uris&uris={:s}".format(self.books_url, value)
|
||||||
|
|
||||||
|
def get_book_data(self, remote_id):
|
||||||
|
data = get_data(remote_id)
|
||||||
|
extracted = list(data.get("entities").values())
|
||||||
|
try:
|
||||||
|
data = extracted[0]
|
||||||
|
except KeyError:
|
||||||
|
raise ConnectorException("Invalid book data")
|
||||||
|
# flatten the data so that images, uri, and claims are on the same level
|
||||||
|
return {
|
||||||
|
**data.get("claims", {}),
|
||||||
|
**{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse_search_data(self, data):
|
||||||
|
return data.get("results")
|
||||||
|
|
||||||
|
def format_search_result(self, search_result):
|
||||||
|
images = search_result.get("image")
|
||||||
|
cover = (
|
||||||
|
"{:s}/img/entities/{:s}".format(self.covers_url, images[0])
|
||||||
|
if images
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
return SearchResult(
|
||||||
|
title=search_result.get("label"),
|
||||||
|
key=self.get_remote_id(search_result.get("uri")),
|
||||||
|
author=search_result.get("description"),
|
||||||
|
view_link="{:s}/entity/{:s}".format(
|
||||||
|
self.base_url, search_result.get("uri")
|
||||||
|
),
|
||||||
|
cover=cover,
|
||||||
|
connector=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
def parse_isbn_search_data(self, data):
|
||||||
|
"""got some daaaata"""
|
||||||
|
results = data.get("entities")
|
||||||
|
if not results:
|
||||||
|
return []
|
||||||
|
return list(results.values())
|
||||||
|
|
||||||
|
def format_isbn_search_result(self, search_result):
|
||||||
|
"""totally different format than a regular search result"""
|
||||||
|
title = search_result.get("claims", {}).get("wdt:P1476", [])
|
||||||
|
if not title:
|
||||||
|
return None
|
||||||
|
return SearchResult(
|
||||||
|
title=title[0],
|
||||||
|
key=self.get_remote_id(search_result.get("uri")),
|
||||||
|
author=search_result.get("description"),
|
||||||
|
view_link="{:s}/entity/{:s}".format(
|
||||||
|
self.base_url, search_result.get("uri")
|
||||||
|
),
|
||||||
|
cover=self.get_cover_url(search_result.get("image")),
|
||||||
|
connector=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_work_data(self, data):
|
||||||
|
return data.get("type") == "work"
|
||||||
|
|
||||||
|
def load_edition_data(self, work_uri):
|
||||||
|
"""get a list of editions for a work"""
|
||||||
|
url = "{:s}?action=reverse-claims&property=wdt:P629&value={:s}".format(
|
||||||
|
self.books_url, work_uri
|
||||||
|
)
|
||||||
|
return get_data(url)
|
||||||
|
|
||||||
|
def get_edition_from_work_data(self, data):
|
||||||
|
data = self.load_edition_data(data.get("uri"))
|
||||||
|
try:
|
||||||
|
uri = data["uris"][0]
|
||||||
|
except KeyError:
|
||||||
|
raise ConnectorException("Invalid book data")
|
||||||
|
return self.get_book_data(self.get_remote_id(uri))
|
||||||
|
|
||||||
|
def get_work_from_edition_data(self, data):
|
||||||
|
try:
|
||||||
|
uri = data["claims"]["wdt:P629"]
|
||||||
|
except KeyError:
|
||||||
|
raise ConnectorException("Invalid book data")
|
||||||
|
return self.get_book_data(self.get_remote_id(uri))
|
||||||
|
|
||||||
|
def get_authors_from_data(self, data):
|
||||||
|
authors = data.get("wdt:P50", [])
|
||||||
|
for author in authors:
|
||||||
|
yield self.get_or_create_author(self.get_remote_id(author))
|
||||||
|
|
||||||
|
def expand_book_data(self, book):
|
||||||
|
work = book
|
||||||
|
# go from the edition to the work, if necessary
|
||||||
|
if isinstance(book, models.Edition):
|
||||||
|
work = book.parent_work
|
||||||
|
|
||||||
|
try:
|
||||||
|
edition_options = self.load_edition_data(work.inventaire_id)
|
||||||
|
except ConnectorException:
|
||||||
|
# who knows, man
|
||||||
|
return
|
||||||
|
|
||||||
|
for edition_uri in edition_options.get("uris"):
|
||||||
|
remote_id = self.get_remote_id(edition_uri)
|
||||||
|
try:
|
||||||
|
data = self.get_book_data(remote_id)
|
||||||
|
except ConnectorException:
|
||||||
|
# who, indeed, knows
|
||||||
|
continue
|
||||||
|
self.create_edition_from_data(work, data)
|
||||||
|
|
||||||
|
def get_cover_url(self, cover_blob, *_):
|
||||||
|
"""format the relative cover url into an absolute one:
|
||||||
|
{"url": "/img/entities/e794783f01b9d4f897a1ea9820b96e00d346994f"}
|
||||||
|
"""
|
||||||
|
# covers may or may not be a list
|
||||||
|
if isinstance(cover_blob, list) and len(cover_blob) > 0:
|
||||||
|
cover_blob = cover_blob[0]
|
||||||
|
cover_id = cover_blob.get("url")
|
||||||
|
if not cover_id:
|
||||||
|
return None
|
||||||
|
# cover may or may not be an absolute url already
|
||||||
|
if re.match(r"^http", cover_id):
|
||||||
|
return cover_id
|
||||||
|
return "%s%s" % (self.covers_url, cover_id)
|
||||||
|
|
||||||
|
def resolve_keys(self, keys):
|
||||||
|
"""cool, it's "wd:Q3156592" now what the heck does that mean"""
|
||||||
|
results = []
|
||||||
|
for uri in keys:
|
||||||
|
try:
|
||||||
|
data = self.get_book_data(self.get_remote_id(uri))
|
||||||
|
except ConnectorException:
|
||||||
|
continue
|
||||||
|
results.append(get_language_code(data.get("labels")))
|
||||||
|
return results
|
||||||
|
|
||||||
|
def get_description(self, links):
|
||||||
|
"""grab an extracted excerpt from wikipedia"""
|
||||||
|
link = links.get("enwiki")
|
||||||
|
if not link:
|
||||||
|
return ""
|
||||||
|
url = "{:s}/api/data?action=wp-extract&lang=en&title={:s}".format(
|
||||||
|
self.base_url, link
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
data = get_data(url)
|
||||||
|
except ConnectorException:
|
||||||
|
return ""
|
||||||
|
return data.get("extract")
|
||||||
|
|
||||||
|
|
||||||
|
def get_language_code(options, code="en"):
|
||||||
|
"""when there are a bunch of translation but we need a single field"""
|
||||||
|
return options.get(code)
|
|
@ -14,8 +14,8 @@ class Connector(AbstractConnector):
|
||||||
def __init__(self, identifier):
|
def __init__(self, identifier):
|
||||||
super().__init__(identifier)
|
super().__init__(identifier)
|
||||||
|
|
||||||
get_first = lambda a: a[0]
|
get_first = lambda a, *args: a[0]
|
||||||
get_remote_id = lambda a: self.base_url + a
|
get_remote_id = lambda a, *args: self.base_url + a
|
||||||
self.book_mappings = [
|
self.book_mappings = [
|
||||||
Mapping("title"),
|
Mapping("title"),
|
||||||
Mapping("id", remote_field="key", formatter=get_remote_id),
|
Mapping("id", remote_field="key", formatter=get_remote_id),
|
||||||
|
|
|
@ -3,7 +3,7 @@ from functools import reduce
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
from django.contrib.postgres.search import SearchRank, SearchVector
|
from django.contrib.postgres.search import SearchRank, SearchVector
|
||||||
from django.db.models import Count, F, Q
|
from django.db.models import Count, OuterRef, Subquery, F, Q
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import models
|
||||||
from .abstract_connector import AbstractConnector, SearchResult
|
from .abstract_connector import AbstractConnector, SearchResult
|
||||||
|
@ -47,7 +47,16 @@ class Connector(AbstractConnector):
|
||||||
|
|
||||||
# when there are multiple editions of the same work, pick the default.
|
# when there are multiple editions of the same work, pick the default.
|
||||||
# it would be odd for this to happen.
|
# it would be odd for this to happen.
|
||||||
results = results.filter(parent_work__default_edition__id=F("id")) or results
|
|
||||||
|
default_editions = models.Edition.objects.filter(
|
||||||
|
parent_work=OuterRef("parent_work")
|
||||||
|
).order_by("-edition_rank")
|
||||||
|
results = (
|
||||||
|
results.annotate(
|
||||||
|
default_id=Subquery(default_editions.values("id")[:1])
|
||||||
|
).filter(default_id=F("id"))
|
||||||
|
or results
|
||||||
|
)
|
||||||
|
|
||||||
search_results = []
|
search_results = []
|
||||||
for result in results:
|
for result in results:
|
||||||
|
@ -60,6 +69,10 @@ class Connector(AbstractConnector):
|
||||||
return search_results
|
return search_results
|
||||||
|
|
||||||
def format_search_result(self, search_result):
|
def format_search_result(self, search_result):
|
||||||
|
cover = None
|
||||||
|
if search_result.cover:
|
||||||
|
cover = "%s%s" % (self.covers_url, search_result.cover)
|
||||||
|
|
||||||
return SearchResult(
|
return SearchResult(
|
||||||
title=search_result.title,
|
title=search_result.title,
|
||||||
key=search_result.remote_id,
|
key=search_result.remote_id,
|
||||||
|
@ -68,7 +81,7 @@ class Connector(AbstractConnector):
|
||||||
if search_result.published_date
|
if search_result.published_date
|
||||||
else None,
|
else None,
|
||||||
connector=self,
|
connector=self,
|
||||||
cover="%s%s" % (self.covers_url, search_result.cover),
|
cover=cover,
|
||||||
confidence=search_result.rank if hasattr(search_result, "rank") else 1,
|
confidence=search_result.rank if hasattr(search_result, "rank") else 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,7 +125,15 @@ def search_identifiers(query, *filters):
|
||||||
|
|
||||||
# when there are multiple editions of the same work, pick the default.
|
# when there are multiple editions of the same work, pick the default.
|
||||||
# it would be odd for this to happen.
|
# it would be odd for this to happen.
|
||||||
return results.filter(parent_work__default_edition__id=F("id")) or results
|
default_editions = models.Edition.objects.filter(
|
||||||
|
parent_work=OuterRef("parent_work")
|
||||||
|
).order_by("-edition_rank")
|
||||||
|
return (
|
||||||
|
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
|
||||||
|
default_id=F("id")
|
||||||
|
)
|
||||||
|
or results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def search_title_author(query, min_confidence, *filters):
|
def search_title_author(query, min_confidence, *filters):
|
||||||
|
@ -140,10 +161,10 @@ def search_title_author(query, min_confidence, *filters):
|
||||||
|
|
||||||
for work_id in set(editions_of_work):
|
for work_id in set(editions_of_work):
|
||||||
editions = results.filter(parent_work=work_id)
|
editions = results.filter(parent_work=work_id)
|
||||||
default = editions.filter(parent_work__default_edition=F("id"))
|
default = editions.order_by("-edition_rank").first()
|
||||||
default_rank = default.first().rank if default.exists() else 0
|
default_rank = default.rank if default else 0
|
||||||
# if mutliple books have the top rank, pick the default edition
|
# if mutliple books have the top rank, pick the default edition
|
||||||
if default_rank == editions.first().rank:
|
if default_rank == editions.first().rank:
|
||||||
yield default.first()
|
yield default
|
||||||
else:
|
else:
|
||||||
yield editions.first()
|
yield editions.first()
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
""" settings book data connectors """
|
""" settings book data connectors """
|
||||||
|
|
||||||
CONNECTORS = ["openlibrary", "self_connector", "bookwyrm_connector"]
|
CONNECTORS = ["openlibrary", "inventaire", "self_connector", "bookwyrm_connector"]
|
||||||
|
|
|
@ -94,6 +94,18 @@ def init_connectors():
|
||||||
priority=2,
|
priority=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Connector.objects.create(
|
||||||
|
identifier="inventaire.io",
|
||||||
|
name="Inventaire",
|
||||||
|
connector_file="inventaire",
|
||||||
|
base_url="https://inventaire.io",
|
||||||
|
books_url="https://inventaire.io/api/entities",
|
||||||
|
covers_url="https://inventaire.io",
|
||||||
|
search_url="https://inventaire.io/api/search?types=works&types=works&search=",
|
||||||
|
isbn_search_url="https://inventaire.io/api/entities?action=by-uris&uris=isbn%3A",
|
||||||
|
priority=3,
|
||||||
|
)
|
||||||
|
|
||||||
Connector.objects.create(
|
Connector.objects.create(
|
||||||
identifier="openlibrary.org",
|
identifier="openlibrary.org",
|
||||||
name="OpenLibrary",
|
name="OpenLibrary",
|
||||||
|
|
30
bookwyrm/migrations/0062_auto_20210406_1731.py
Normal file
30
bookwyrm/migrations/0062_auto_20210406_1731.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Generated by Django 3.1.6 on 2021-04-06 17:31
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0061_auto_20210402_1435"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveConstraint(
|
||||||
|
model_name="connector",
|
||||||
|
name="connector_file_valid",
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="connector",
|
||||||
|
name="connector_file",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("openlibrary", "Openlibrary"),
|
||||||
|
("inventaire", "Inventaire"),
|
||||||
|
("self_connector", "Self Connector"),
|
||||||
|
("bookwyrm_connector", "Bookwyrm Connector"),
|
||||||
|
],
|
||||||
|
max_length=255,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
63
bookwyrm/migrations/0063_auto_20210407_0045.py
Normal file
63
bookwyrm/migrations/0063_auto_20210407_0045.py
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Generated by Django 3.1.6 on 2021-04-07 00:45
|
||||||
|
|
||||||
|
import bookwyrm.models.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0062_auto_20210406_1731"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="author",
|
||||||
|
name="bnf_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="author",
|
||||||
|
name="gutenberg_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="author",
|
||||||
|
name="inventaire_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="author",
|
||||||
|
name="isni",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="author",
|
||||||
|
name="viaf_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="book",
|
||||||
|
name="bnf_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="book",
|
||||||
|
name="inventaire_id",
|
||||||
|
field=bookwyrm.models.fields.CharField(
|
||||||
|
blank=True, max_length=255, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Generated by Django 3.2 on 2021-04-26 21:32
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0063_auto_20210407_0045"),
|
||||||
|
("bookwyrm", "0070_auto_20210423_0121"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = []
|
17
bookwyrm/migrations/0072_remove_work_default_edition.py
Normal file
17
bookwyrm/migrations/0072_remove_work_default_edition.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 3.2 on 2021-04-28 22:16
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0071_merge_0063_auto_20210407_0045_0070_auto_20210423_0121"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="work",
|
||||||
|
name="default_edition",
|
||||||
|
),
|
||||||
|
]
|
|
@ -14,6 +14,15 @@ class Author(BookDataModel):
|
||||||
wikipedia_link = fields.CharField(
|
wikipedia_link = fields.CharField(
|
||||||
max_length=255, blank=True, null=True, deduplication_field=True
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
)
|
)
|
||||||
|
isni = fields.CharField(
|
||||||
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
|
)
|
||||||
|
viaf_id = fields.CharField(
|
||||||
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
|
)
|
||||||
|
gutenberg_id = fields.CharField(
|
||||||
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
|
)
|
||||||
# idk probably other keys would be useful here?
|
# idk probably other keys would be useful here?
|
||||||
born = fields.DateTimeField(blank=True, null=True)
|
born = fields.DateTimeField(blank=True, null=True)
|
||||||
died = fields.DateTimeField(blank=True, null=True)
|
died = fields.DateTimeField(blank=True, null=True)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
""" database schema for books and shelves """
|
""" database schema for books and shelves """
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.db import models, transaction
|
from django.db import models
|
||||||
from model_utils.managers import InheritanceManager
|
from model_utils.managers import InheritanceManager
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN, DEFAULT_LANGUAGE
|
||||||
|
|
||||||
from .activitypub_mixin import OrderedCollectionPageMixin, ObjectMixin
|
from .activitypub_mixin import OrderedCollectionPageMixin, ObjectMixin
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
|
@ -19,12 +19,18 @@ class BookDataModel(ObjectMixin, BookWyrmModel):
|
||||||
openlibrary_key = fields.CharField(
|
openlibrary_key = fields.CharField(
|
||||||
max_length=255, blank=True, null=True, deduplication_field=True
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
)
|
)
|
||||||
|
inventaire_id = fields.CharField(
|
||||||
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
|
)
|
||||||
librarything_key = fields.CharField(
|
librarything_key = fields.CharField(
|
||||||
max_length=255, blank=True, null=True, deduplication_field=True
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
)
|
)
|
||||||
goodreads_key = fields.CharField(
|
goodreads_key = fields.CharField(
|
||||||
max_length=255, blank=True, null=True, deduplication_field=True
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
)
|
)
|
||||||
|
bnf_id = fields.CharField( # Bibliothèque nationale de France
|
||||||
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
|
)
|
||||||
|
|
||||||
last_edited_by = fields.ForeignKey(
|
last_edited_by = fields.ForeignKey(
|
||||||
"User",
|
"User",
|
||||||
|
@ -137,10 +143,6 @@ class Work(OrderedCollectionPageMixin, Book):
|
||||||
lccn = fields.CharField(
|
lccn = fields.CharField(
|
||||||
max_length=255, blank=True, null=True, deduplication_field=True
|
max_length=255, blank=True, null=True, deduplication_field=True
|
||||||
)
|
)
|
||||||
# this has to be nullable but should never be null
|
|
||||||
default_edition = fields.ForeignKey(
|
|
||||||
"Edition", on_delete=models.PROTECT, null=True, load_remote=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""set some fields on the edition object"""
|
"""set some fields on the edition object"""
|
||||||
|
@ -149,18 +151,10 @@ class Work(OrderedCollectionPageMixin, Book):
|
||||||
edition.save()
|
edition.save()
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
def get_default_edition(self):
|
@property
|
||||||
|
def default_edition(self):
|
||||||
"""in case the default edition is not set"""
|
"""in case the default edition is not set"""
|
||||||
return self.default_edition or self.editions.order_by("-edition_rank").first()
|
return self.editions.order_by("-edition_rank").first()
|
||||||
|
|
||||||
@transaction.atomic()
|
|
||||||
def reset_default_edition(self):
|
|
||||||
"""sets a new default edition based on computed rank"""
|
|
||||||
self.default_edition = None
|
|
||||||
# editions are re-ranked implicitly
|
|
||||||
self.save()
|
|
||||||
self.default_edition = self.get_default_edition()
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def to_edition_list(self, **kwargs):
|
def to_edition_list(self, **kwargs):
|
||||||
"""an ordered collection of editions"""
|
"""an ordered collection of editions"""
|
||||||
|
@ -214,17 +208,20 @@ class Edition(Book):
|
||||||
activity_serializer = activitypub.Edition
|
activity_serializer = activitypub.Edition
|
||||||
name_field = "title"
|
name_field = "title"
|
||||||
|
|
||||||
def get_rank(self, ignore_default=False):
|
def get_rank(self):
|
||||||
"""calculate how complete the data is on this edition"""
|
"""calculate how complete the data is on this edition"""
|
||||||
if (
|
|
||||||
not ignore_default
|
|
||||||
and self.parent_work
|
|
||||||
and self.parent_work.default_edition == self
|
|
||||||
):
|
|
||||||
# default edition has the highest rank
|
|
||||||
return 20
|
|
||||||
rank = 0
|
rank = 0
|
||||||
|
# big ups for havinga cover
|
||||||
rank += int(bool(self.cover)) * 3
|
rank += int(bool(self.cover)) * 3
|
||||||
|
# is it in the instance's preferred language?
|
||||||
|
rank += int(bool(DEFAULT_LANGUAGE in self.languages))
|
||||||
|
# prefer print editions
|
||||||
|
if self.physical_format:
|
||||||
|
rank += int(
|
||||||
|
bool(self.physical_format.lower() in ["paperback", "hardcover"])
|
||||||
|
)
|
||||||
|
|
||||||
|
# does it have metadata?
|
||||||
rank += int(bool(self.isbn_13))
|
rank += int(bool(self.isbn_13))
|
||||||
rank += int(bool(self.isbn_10))
|
rank += int(bool(self.isbn_10))
|
||||||
rank += int(bool(self.oclc_number))
|
rank += int(bool(self.oclc_number))
|
||||||
|
@ -242,6 +239,12 @@ class Edition(Book):
|
||||||
if self.isbn_10 and not self.isbn_13:
|
if self.isbn_10 and not self.isbn_13:
|
||||||
self.isbn_13 = isbn_10_to_13(self.isbn_10)
|
self.isbn_13 = isbn_10_to_13(self.isbn_10)
|
||||||
|
|
||||||
|
# normalize isbn format
|
||||||
|
if self.isbn_10:
|
||||||
|
self.isbn_10 = re.sub(r"[^0-9X]", "", self.isbn_10)
|
||||||
|
if self.isbn_13:
|
||||||
|
self.isbn_13 = re.sub(r"[^0-9X]", "", self.isbn_13)
|
||||||
|
|
||||||
# set rank
|
# set rank
|
||||||
self.edition_rank = self.get_rank()
|
self.edition_rank = self.get_rank()
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,6 @@ class Connector(BookWyrmModel):
|
||||||
# when to reset the query count back to 0 (ie, after 1 day)
|
# when to reset the query count back to 0 (ie, after 1 day)
|
||||||
query_count_expiry = models.DateTimeField(auto_now_add=True, blank=True)
|
query_count_expiry = models.DateTimeField(auto_now_add=True, blank=True)
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""check that there's code to actually use this connector"""
|
|
||||||
|
|
||||||
constraints = [
|
|
||||||
models.CheckConstraint(
|
|
||||||
check=models.Q(connector_file__in=ConnectorFiles),
|
|
||||||
name="connector_file_valid",
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{} ({})".format(
|
return "{} ({})".format(
|
||||||
self.identifier,
|
self.identifier,
|
||||||
|
|
|
@ -11,6 +11,7 @@ DOMAIN = env("DOMAIN")
|
||||||
VERSION = "0.0.1"
|
VERSION = "0.0.1"
|
||||||
|
|
||||||
PAGE_LENGTH = env("PAGE_LENGTH", 15)
|
PAGE_LENGTH = env("PAGE_LENGTH", 15)
|
||||||
|
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")
|
||||||
|
|
||||||
# celery
|
# celery
|
||||||
CELERY_BROKER = env("CELERY_BROKER")
|
CELERY_BROKER = env("CELERY_BROKER")
|
||||||
|
@ -34,6 +35,8 @@ LOCALE_PATHS = [
|
||||||
os.path.join(BASE_DIR, "locale"),
|
os.path.join(BASE_DIR, "locale"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,6 @@ body {
|
||||||
white-space: nowrap !important;
|
white-space: nowrap !important;
|
||||||
width: 0.01em !important;
|
width: 0.01em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-0-mobile {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.is-transparent {
|
.button.is-transparent {
|
||||||
|
@ -132,7 +128,7 @@ body {
|
||||||
*
|
*
|
||||||
* \e9d9: filled star
|
* \e9d9: filled star
|
||||||
* \e9d7: empty star;
|
* \e9d7: empty star;
|
||||||
******************************************************************************/
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
.form-rate-stars {
|
.form-rate-stars {
|
||||||
width: max-content;
|
width: max-content;
|
||||||
|
@ -158,70 +154,67 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Book covers
|
/** Book covers
|
||||||
|
*
|
||||||
|
* - .is-cover gives the behaviour of the cover and its surrounding. (optional)
|
||||||
|
* - .cover-container gives the dimensions and position (for borders, image and other elements).
|
||||||
|
* - .book-cover is positioned and sized based on its container.
|
||||||
|
*
|
||||||
|
* To have the cover within specific dimensions, specify a width or height for
|
||||||
|
* standard bulma’s named breapoints:
|
||||||
|
*
|
||||||
|
* `is-(w|h)-(auto|xs|s|m|l|xl|xxl)[-(mobile|tablet|desktop)]`
|
||||||
|
*
|
||||||
|
* The cover will be centered horizontally and vertically within those dimensions.
|
||||||
|
*
|
||||||
|
* When using `.column.is-N`, add `.is-w-auto` to the container so that the flex
|
||||||
|
* calculations are not biased by the default `max-content`.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
.column.is-cover {
|
||||||
|
flex-grow: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column.is-cover,
|
||||||
|
.column.is-cover + .column {
|
||||||
|
flex-basis: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.cover-container {
|
.cover-container {
|
||||||
height: 250px;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: 250px;
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cover-container.is-large {
|
/* Book cover
|
||||||
height: max-content;
|
* -------------------------------------------------------------------------- */
|
||||||
max-width: 330px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cover-container.is-large img {
|
|
||||||
max-height: 500px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cover-container.is-medium {
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cover-container.is-small {
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
.cover-container {
|
|
||||||
height: 200px;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cover-container.is-medium {
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.book-cover {
|
.book-cover {
|
||||||
height: 100%;
|
display: block;
|
||||||
object-fit: scale-down;
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
|
/* Useful when stretching under-sized images. */
|
||||||
|
image-rendering: optimizeQuality;
|
||||||
|
image-rendering: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-cover {
|
/* Cover caption
|
||||||
position: relative;
|
* -------------------------------------------------------------------------- */
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-cover div {
|
.no-cover .cover_caption {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 1em;
|
|
||||||
color: white;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
text-align: center;
|
padding: 0.25em;
|
||||||
}
|
font-size: 0.75em;
|
||||||
|
color: white;
|
||||||
.cover-container.is-medium .no-cover div {
|
background-color: #002549;
|
||||||
font-size: 0.9em;
|
|
||||||
padding: 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cover-container.is-small .no-cover div {
|
|
||||||
font-size: 0.7em;
|
|
||||||
padding: 0.1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Avatars
|
/** Avatars
|
||||||
|
@ -232,16 +225,6 @@ body {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-32x32 {
|
|
||||||
min-width: 32px;
|
|
||||||
min-height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-96x96 {
|
|
||||||
min-width: 96px;
|
|
||||||
min-height: 96px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Statuses: Quotes
|
/** Statuses: Quotes
|
||||||
*
|
*
|
||||||
* \e906: icon-quote-open
|
* \e906: icon-quote-open
|
||||||
|
@ -346,3 +329,386 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dimensions
|
||||||
|
* @todo These could be in rem.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
.is-32x32 {
|
||||||
|
min-width: 32px !important;
|
||||||
|
min-height: 32px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-96x96 {
|
||||||
|
min-width: 96px !important;
|
||||||
|
min-height: 96px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-auto {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xs {
|
||||||
|
width: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-s {
|
||||||
|
width: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-m {
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-l {
|
||||||
|
width: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xl {
|
||||||
|
width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xxl {
|
||||||
|
width: 500px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xs {
|
||||||
|
height: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-s {
|
||||||
|
height: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-m {
|
||||||
|
height: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-l {
|
||||||
|
height: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xl {
|
||||||
|
height: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xxl {
|
||||||
|
height: 500px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.is-w-auto-mobile {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xs-mobile {
|
||||||
|
width: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-s-mobile {
|
||||||
|
width: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-m-mobile {
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-l-mobile {
|
||||||
|
width: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xl-mobile {
|
||||||
|
width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xxl-mobile {
|
||||||
|
width: 500px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xs-mobile {
|
||||||
|
height: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-s-mobile {
|
||||||
|
height: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-m-mobile {
|
||||||
|
height: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-l-mobile {
|
||||||
|
height: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xl-mobile {
|
||||||
|
height: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xxl-mobile {
|
||||||
|
height: 500px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 769px) {
|
||||||
|
.is-w-auto-tablet {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xs-tablet {
|
||||||
|
width: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-s-tablet {
|
||||||
|
width: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-m-tablet {
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-l-tablet {
|
||||||
|
width: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xl-tablet {
|
||||||
|
width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xxl-tablet {
|
||||||
|
width: 500px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xs-tablet {
|
||||||
|
height: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-s-tablet {
|
||||||
|
height: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-m-tablet {
|
||||||
|
height: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-l-tablet {
|
||||||
|
height: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xl-tablet {
|
||||||
|
height: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xxl-tablet {
|
||||||
|
height: 500px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1024px) {
|
||||||
|
.is-w-auto-desktop {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xs-desktop {
|
||||||
|
width: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-s-desktop {
|
||||||
|
width: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-m-desktop {
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-l-desktop {
|
||||||
|
width: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xl-desktop {
|
||||||
|
width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-w-xxl-desktop {
|
||||||
|
width: 500px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xs-desktop {
|
||||||
|
height: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-s-desktop {
|
||||||
|
height: 100px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-m-desktop {
|
||||||
|
height: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-l-desktop {
|
||||||
|
height: 200px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xl-desktop {
|
||||||
|
height: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-h-xxl-desktop {
|
||||||
|
height: 500px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alignments
|
||||||
|
*
|
||||||
|
* Use them with `.align.to-(c|t|r|b|l)[-(mobile|tablet)]`
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* Flex item position
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.align {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-c {
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-t {
|
||||||
|
align-items: flex-start !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-r {
|
||||||
|
justify-content: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-b {
|
||||||
|
align-items: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-l {
|
||||||
|
justify-content: flex-start !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.align.to-c-mobile {
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-t-mobile {
|
||||||
|
align-items: flex-start !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-r-mobile {
|
||||||
|
justify-content: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-b-mobile {
|
||||||
|
align-items: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-l-mobile {
|
||||||
|
justify-content: flex-start !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 769px) {
|
||||||
|
.align.to-c-tablet {
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-t-tablet {
|
||||||
|
align-items: flex-start !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-r-tablet {
|
||||||
|
justify-content: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-b-tablet {
|
||||||
|
align-items: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align.to-l-tablet {
|
||||||
|
justify-content: flex-start !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spacings
|
||||||
|
*
|
||||||
|
* Those are supplementary rules to Bulma’s. They follow the same conventions.
|
||||||
|
* Add those you’ll need.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
.mr-auto {
|
||||||
|
margin-right: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-auto {
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.m-0-mobile {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-auto-mobile {
|
||||||
|
margin-right: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-auto-mobile {
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-3-mobile {
|
||||||
|
margin-top: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-3-mobile {
|
||||||
|
margin-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-3-mobile {
|
||||||
|
margin-right: 0.75rem !important;
|
||||||
|
margin-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-3-mobile {
|
||||||
|
margin-top: 0.75rem !important;
|
||||||
|
margin-bottom: 0.75rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 769px) {
|
||||||
|
.m-0-tablet {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-auto-tablet {
|
||||||
|
margin-right: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-auto-tablet {
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-3-tablet {
|
||||||
|
margin-top: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-3-tablet {
|
||||||
|
margin-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-3-tablet {
|
||||||
|
margin-right: 0.75rem !important;
|
||||||
|
margin-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-3-tablet {
|
||||||
|
margin-top: 0.75rem !important;
|
||||||
|
margin-bottom: 0.75rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
bookwyrm/static/css/vendor/bulma.min.css
vendored
2
bookwyrm/static/css/vendor/bulma.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -48,10 +48,9 @@
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-one-fifth">
|
<div class="column is-one-fifth">
|
||||||
<div class="is-clipped">
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m-mobile' %}
|
||||||
{% include 'snippets/book_cover.html' with book=book size=large %}
|
{% include 'snippets/rate_action.html' with user=request.user book=book %}
|
||||||
{% include 'snippets/rate_action.html' with user=request.user book=book %}
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' %}
|
{% include 'snippets/shelve_button/shelve_button.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -81,6 +80,9 @@
|
||||||
{% if book.openlibrary_key %}
|
{% if book.openlibrary_key %}
|
||||||
<p><a href="https://openlibrary.org/books/{{ book.openlibrary_key }}" target="_blank" rel="noopener">{% trans "View on OpenLibrary" %}</a></p>
|
<p><a href="https://openlibrary.org/books/{{ book.openlibrary_key }}" target="_blank" rel="noopener">{% trans "View on OpenLibrary" %}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if book.inventaire_id %}
|
||||||
|
<p><a href="https://inventaire.io/entity/{{ book.inventaire_id }}" target="_blank" rel="noopener">{% trans "View on Inventaire" %}</a></p>
|
||||||
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -169,10 +169,11 @@
|
||||||
<div class="column is-half">
|
<div class="column is-half">
|
||||||
<h2 class="title is-4">{% trans "Cover" %}</h2>
|
<h2 class="title is-4">{% trans "Cover" %}</h2>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-narrow">
|
<div class="column is-3 is-cover">
|
||||||
{% include 'snippets/book_cover.html' with book=book size="small" %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-xl-mobile is-w-auto-tablet' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-narrow">
|
|
||||||
|
<div class="column">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<p>
|
<p>
|
||||||
<label class="label" for="id_cover">{% trans "Upload cover:" %}</label>
|
<label class="label" for="id_cover">{% trans "Upload cover:" %}</label>
|
||||||
|
|
|
@ -13,32 +13,34 @@
|
||||||
|
|
||||||
<div class="block">
|
<div class="block">
|
||||||
{% for book in editions %}
|
{% for book in editions %}
|
||||||
<div class="columns">
|
<div class="columns is-gapless mb-6">
|
||||||
<div class="column is-2">
|
<div class="column is-cover">
|
||||||
<a href="/book/{{ book.id }}">
|
<a href="/book/{{ book.id }}">
|
||||||
{% include 'snippets/book_cover.html' with book=book size="medium" %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-w-m is-h-m align to-l-mobile' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-7">
|
|
||||||
<h2 class="title is-5">
|
<div class="column my-3-mobile ml-3-tablet mr-auto">
|
||||||
|
<h2 class="title is-5 mb-1">
|
||||||
<a href="/book/{{ book.id }}" class="has-text-black">
|
<a href="/book/{{ book.id }}" class="has-text-black">
|
||||||
{{ book.title }}
|
{{ book.title }}
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{% with book=book %}
|
{% with book=book %}
|
||||||
<div class="columns is-multiline">
|
<div class="columns is-multiline is-gapless ml-3-tablet">
|
||||||
<div class="column is-half">
|
<div class="column is-half">
|
||||||
{% include 'book/publisher_info.html' %}
|
{% include 'book/publisher_info.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column is-half ">
|
<div class="column ml-3-tablet">
|
||||||
{% include 'book/book_identifiers.html' %}
|
{% include 'book/book_identifiers.html' %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-3">
|
|
||||||
|
<div class="column is-narrow">
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
|
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,14 +11,15 @@
|
||||||
{% with 0|uuid as uuid %}
|
{% with 0|uuid as uuid %}
|
||||||
<div class="box columns">
|
<div class="box columns">
|
||||||
{% if book %}
|
{% if book %}
|
||||||
<div class="column is-one-third">
|
<div class="column is-3 is-cover">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
|
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto-tablet is-h-l-mobile' %}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="title is-6">{% include 'snippets/book_titleby.html' with book=book %}</h3>
|
<h3 class="title is-6">{% include 'snippets/book_titleby.html' with book=book %}</h3>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="column is-two-thirds">
|
<div class="column">
|
||||||
{% if draft.reply_parent %}
|
{% if draft.reply_parent %}
|
||||||
{% include 'snippets/status/status.html' with status=draft.reply_parent no_interact=True %}
|
{% include 'snippets/status/status.html' with status=draft.reply_parent no_interact=True %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,19 +1,38 @@
|
||||||
|
|
||||||
{% load bookwyrm_tags %}
|
{% load bookwyrm_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% if book %}
|
{% if book %}
|
||||||
<div class="columns">
|
{% with book=book %}
|
||||||
<div class="column is-narrow">
|
<div class="columns is-gapless">
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="large" %}</a>
|
<div class="column is-5-tablet is-cover">
|
||||||
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
<a
|
||||||
</div>
|
class="align to-b to-l"
|
||||||
<div class="column">
|
href="{{ book.local_path }}"
|
||||||
<h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
|
>{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %}</a>
|
||||||
{% if book.authors %}
|
|
||||||
<p class="subtitle is-5">{% trans "by" %} {% include 'snippets/authors.html' with book=book %}</p>
|
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
||||||
{% endif %}
|
</div>
|
||||||
{% if book|book_description %}
|
|
||||||
<blockquote class="content">{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}</blockquote>
|
|
||||||
{% endif %}
|
<div class="column mt-3-mobile ml-3-tablet">
|
||||||
</div>
|
<h3 class="title is-5">
|
||||||
</div>
|
<a href="/book/{{ book.id }}">{{ book.title }}</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{% if book.authors %}
|
||||||
|
<p class="subtitle is-5">
|
||||||
|
{% trans "by" %}
|
||||||
|
{% include 'snippets/authors.html' %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if book|book_description %}
|
||||||
|
<blockquote class="content">
|
||||||
|
{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}
|
||||||
|
</blockquote>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
|
|
||||||
{% load bookwyrm_tags %}
|
{% load bookwyrm_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% if book %}
|
{% if book %}
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
|
{% with book=book %}
|
||||||
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
<a href="{{ book.local_path }}">
|
||||||
|
{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %}
|
||||||
|
</a>
|
||||||
|
|
||||||
<h3 class="title is-6"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
|
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
||||||
{% if book.authors %}
|
|
||||||
<p class="subtitle is-6">{% trans "by" %} {% include 'snippets/authors.html' with book=book %}</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
<h3 class="title is-6">
|
||||||
|
<a href="/book/{{ book.id }}">{{ book.title }}</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{% if book.authors %}
|
||||||
|
<p class="subtitle is-6">
|
||||||
|
{% trans "by" %}
|
||||||
|
{% include 'snippets/authors.html' %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
aria-label="{{ book.title }}"
|
aria-label="{{ book.title }}"
|
||||||
aria-selected="{% if active_book == book.id|stringformat:'d' %}true{% elif shelf_counter == 1 and forloop.first %}true{% else %}false{% endif %}"
|
aria-selected="{% if active_book == book.id|stringformat:'d' %}true{% elif shelf_counter == 1 and forloop.first %}true{% else %}false{% endif %}"
|
||||||
aria-controls="book-{{ book.id }}">
|
aria-controls="book-{{ book.id }}">
|
||||||
{% include 'snippets/book_cover.html' with book=book size="medium" %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="column is-narrow is-clipped has-text-centered">
|
<div class="column is-cover">
|
||||||
{% include 'snippets/book_cover.html' with book=book %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-l is-h-m-mobile' %}
|
||||||
<label class="label" for="id_shelve_{{ book.id }}">
|
|
||||||
<div class="select is-small">
|
<div class="select is-small mt-1 mb-3">
|
||||||
<select name="{{ book.id }}" aria-label="{% blocktrans with book_title=book.title %}Have you read {{ book_title }}?{% endblocktrans %}">
|
<select name="{{ book.id }}" aria-label="{% blocktrans with book_title=book.title %}Have you read {{ book_title }}?{% endblocktrans %}">
|
||||||
<option disabled selected value>Add to your books</option>
|
<option disabled selected value>Add to your books</option>
|
||||||
{% for shelf in request.user.shelf_set.all %}
|
{% for shelf in request.user.shelf_set.all %}
|
||||||
|
|
|
@ -23,34 +23,43 @@
|
||||||
|
|
||||||
<form class="block" name="add-books" method="post" action="{% url 'get-started-books' %}">
|
<form class="block" name="add-books" method="post" action="{% url 'get-started-books' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<h3 class="title is-5">{% trans "Suggested Books" %}</h3>
|
<h3 class="title is-5">{% trans "Suggested Books" %}</h3>
|
||||||
<fieldset name="books" class="columns scroll-x is-mobile">
|
|
||||||
{% if book_results %}
|
<div class="block scroll-x">
|
||||||
<div class="column is-narrow content">
|
<fieldset name="books" class="columns is-mobile">
|
||||||
<p class="help mb-0">Search results</p>
|
{% if book_results %}
|
||||||
<div class="columns is-mobile">
|
<div class="column is-narrow">
|
||||||
{% for book in book_results %}
|
<p class="help mb-0">Search results</p>
|
||||||
{% include 'get_started/book_preview.html' %}
|
|
||||||
{% endfor %}
|
<div class="columns is-mobile">
|
||||||
</div>
|
{% for book in book_results %}
|
||||||
</div>
|
{% include 'get_started/book_preview.html' %}
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
{% if popular_books %}
|
</div>
|
||||||
<div class="column is-narrow content">
|
</div>
|
||||||
<p class="help mb-0">
|
{% endif %}
|
||||||
{% blocktrans %}Popular on {{ site_name }}{% endblocktrans %}
|
|
||||||
</p>
|
{% if popular_books %}
|
||||||
<div class="columns is-mobile">
|
<div class="column is-narrow">
|
||||||
{% for book in popular_books %}
|
<p class="help mb-0">
|
||||||
{% include 'get_started/book_preview.html' %}
|
{% blocktrans %}Popular on {{ site_name }}{% endblocktrans %}
|
||||||
{% endfor %}
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
<div class="columns is-mobile">
|
||||||
{% endif %}
|
{% for book in popular_books %}
|
||||||
{% if not book_results and not popular_books %}
|
{% include 'get_started/book_preview.html' %}
|
||||||
<p><em>{% trans "No books found" %}</em></p>
|
{% endfor %}
|
||||||
{% endif %}
|
</div>
|
||||||
</fieldset>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if not book_results and not popular_books %}
|
||||||
|
<p><em>{% trans "No books found" %}</em></p>
|
||||||
|
{% endif %}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="button is-primary">{% trans "Save & continue" %}</button>
|
<button type="submit" class="button is-primary">{% trans "Save & continue" %}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -45,21 +45,22 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{% if goal.books %}
|
{% if goal.books %}
|
||||||
<section class="content">
|
<section>
|
||||||
<h2>
|
<h2 class="title is-4">
|
||||||
{% if goal.user == request.user %}
|
{% if goal.user == request.user %}
|
||||||
{% blocktrans %}Your {{ year }} Books{% endblocktrans %}
|
{% blocktrans %}Your {{ year }} Books{% endblocktrans %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% blocktrans with username=goal.user.display_name %}{{ username }}'s {{ year }} Books{% endblocktrans %}
|
{% blocktrans with username=goal.user.display_name %}{{ username }}'s {{ year }} Books{% endblocktrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="columns is-multiline">
|
|
||||||
|
<div class="columns is-mobile is-multiline">
|
||||||
{% for book in goal.books %}
|
{% for book in goal.books %}
|
||||||
<div class="column is-one-fifth">
|
<div class="column is-cover">
|
||||||
<div class="is-clipped">
|
<a href="{{ book.book.local_path }}">
|
||||||
<a href="{{ book.book.local_path }}">{% include 'snippets/book_cover.html' with book=book.book %}</a>
|
{% include 'snippets/book_cover.html' with book=book.book cover_class='is-h-xl is-h-l-mobile' %}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
<td>
|
<td>
|
||||||
{% if item.book %}
|
{% if item.book %}
|
||||||
<a href="/book/{{ item.book.id }}">
|
<a href="/book/{{ item.book.id }}">
|
||||||
{% include 'snippets/book_cover.html' with book=item.book size='small' %}
|
{% include 'snippets/book_cover.html' with book=item.book cover_class='is-h-s' %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -2,49 +2,71 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
|
|
||||||
<section class="content block">
|
<section class="block">
|
||||||
<h2>{% trans "Pending Books" %}</h2>
|
<div class="columns is-mobile is-multiline is-align-items-baseline">
|
||||||
<p><a href="{% url 'list' list.id %}">{% trans "Go to list" %}</a></p>
|
<div class="column is-narrow">
|
||||||
|
<h2 class="title is-4">{% trans "Pending Books" %}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="column is-narrow"><a href="{% url 'list' list.id %}">{% trans "Go to list" %}</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if not pending.exists %}
|
{% if not pending.exists %}
|
||||||
<p>{% trans "You're all set!" %}</p>
|
<p>{% trans "You're all set!" %}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<table class="table is-striped">
|
|
||||||
<tr>
|
<dl>
|
||||||
<th></th>
|
|
||||||
<th>{% trans "Book" %}</th>
|
|
||||||
<th>{% trans "Suggested by" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
{% for item in pending %}
|
{% for item in pending %}
|
||||||
<tr>
|
{% with book=item.book %}
|
||||||
<td>
|
<div
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=item.book size="small" %}</a>
|
class="
|
||||||
</td>
|
columns is-gapless
|
||||||
<td>
|
is-vcentered is-justify-content-space-between
|
||||||
{% include 'snippets/book_titleby.html' with book=item.book %}
|
mb-6
|
||||||
</td>
|
"
|
||||||
<td>
|
>
|
||||||
<a href="{{ item.user.local_path }}">{{ item.user.display_name }}</a>
|
<dt class="column mr-auto">
|
||||||
</td>
|
<div class="columns is-mobile is-gapless is-vcentered">
|
||||||
<td>
|
<a
|
||||||
<div class="field has-addons">
|
class="column is-cover"
|
||||||
<form class="control" method="POST" action="{% url 'list-curate' list.id %}">
|
href="{{ book.local_path }}"
|
||||||
{% csrf_token %}
|
aria-hidden="true"
|
||||||
<input type="hidden" name="item" value="{{ item.id }}">
|
>
|
||||||
<input type="hidden" name="approved" value="true">
|
{% include 'snippets/book_cover.html' with cover_class='is-w-xs-mobile is-w-s is-h-xs-mobile is-h-s' %}
|
||||||
<button class="button">{% trans "Approve" %}</button>
|
</a>
|
||||||
</form>
|
|
||||||
<form class="control" method="POST" action="{% url 'list-curate' list.id %}">
|
<div class="column ml-3">
|
||||||
{% csrf_token %}
|
{% include 'snippets/book_titleby.html' %}
|
||||||
<input type="hidden" name="item" value="{{ item.id }}">
|
</div>
|
||||||
<input type="hidden" name="approved" value="false">
|
</div>
|
||||||
<button class="button is-danger is-light">{% trans "Discard" %}</button>
|
</dt>
|
||||||
</div>
|
|
||||||
</form>
|
<dd class="column is-4-tablet mx-3-tablet my-3-mobile">
|
||||||
</td>
|
{% trans "Suggested by" %}
|
||||||
</tr>
|
|
||||||
|
<a href="{{ item.user.local_path }}">
|
||||||
|
{{ item.user.display_name }}
|
||||||
|
</a>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dd class="column is-narrow field has-addons">
|
||||||
|
<form class="control" method="POST" action="{% url 'list-curate' list.id %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="item" value="{{ item.id }}">
|
||||||
|
<input type="hidden" name="approved" value="true">
|
||||||
|
<button class="button">{% trans "Approve" %}</button>
|
||||||
|
</form>
|
||||||
|
<form class="control" method="POST" action="{% url 'list-curate' list.id %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="item" value="{{ item.id }}">
|
||||||
|
<input type="hidden" name="approved" value="false">
|
||||||
|
<button class="button is-danger is-light">{% trans "Discard" %}</button>
|
||||||
|
</form>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</dl>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -28,18 +28,29 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<ol start="{{ items.start_index }}">
|
<ol start="{{ items.start_index }}">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<li class="block pb-3">
|
<li class="block mb-5">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content columns p-0 pr-2 mb-0 is-mobile">
|
{% with book=item.book %}
|
||||||
<div class="column is-narrow pt-0 pb-0">
|
<div
|
||||||
<a href="{{ item.book.local_path }}">{% include 'snippets/book_cover.html' with book=item.book size="medium" %}</a>
|
class="
|
||||||
|
card-content p-0 mb-0
|
||||||
|
columns is-mobile is-gapless
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="column is-2-mobile is-cover align to-t">
|
||||||
|
<a href="{{ item.book.local_path }}" aria-hidden="true">
|
||||||
|
{% include 'snippets/book_cover.html' with cover_class='is-w-auto is-h-m-tablet' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column ml-3">
|
||||||
|
<span>{% include 'snippets/book_titleby.html' %}</span>
|
||||||
|
{% include 'snippets/stars.html' with rating=item.book|rating:request.user %}
|
||||||
|
{% include 'snippets/shelve_button/shelve_button.html' %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-flex-direction-column is-align-items-self-start">
|
{% endwith %}
|
||||||
<span>{% include 'snippets/book_titleby.html' with book=item.book %}</span>
|
|
||||||
{% include 'snippets/stars.html' with rating=item.book|rating:request.user %}
|
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' with book=item.book %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer has-background-white-bis is-align-items-baseline">
|
<div class="card-footer has-background-white-bis is-align-items-baseline">
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
<div>
|
<div>
|
||||||
|
@ -76,7 +87,7 @@
|
||||||
{% include "snippets/pagination.html" with page=items %}
|
{% include "snippets/pagination.html" with page=items %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="column is-one-quarter content">
|
<section class="column is-one-quarter">
|
||||||
<h2>{% trans "Sort List" %}</h2>
|
<h2>{% trans "Sort List" %}</h2>
|
||||||
<form name="sort" action="{% url 'list' list.id %}" method="GET" class="block">
|
<form name="sort" action="{% url 'list' list.id %}" method="GET" class="block">
|
||||||
<label class="label" for="id_sort_by">{% trans "Sort By" %}</label>
|
<label class="label" for="id_sort_by">{% trans "Sort By" %}</label>
|
||||||
|
@ -118,24 +129,36 @@
|
||||||
<p>{% trans "No books found" %}</p>
|
<p>{% trans "No books found" %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for book in suggested_books %}
|
|
||||||
{% if book %}
|
{% if suggested_books|length > 0 %}
|
||||||
<div class="block columns is-mobile">
|
{% for book in suggested_books %}
|
||||||
<div class="column is-narrow">
|
<div class="columns is-mobile is-gapless">
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
|
<a
|
||||||
</div>
|
class="column is-2-mobile is-3-tablet is-cover align to-c"
|
||||||
<div class="column">
|
href="{{ book.local_path }}"
|
||||||
<p>{% include 'snippets/book_titleby.html' with book=book %}</p>
|
aria-hidden="true"
|
||||||
<form name="add-book" method="post" action="{% url 'list-add-book' %}{% if query %}?q={{ query }}{% endif %}">
|
>
|
||||||
{% csrf_token %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto is-h-s-mobile align to-t' %}
|
||||||
<input type="hidden" name="book" value="{{ book.id }}">
|
</a>
|
||||||
<input type="hidden" name="list" value="{{ list.id }}">
|
|
||||||
<button type="submit" class="button is-small is-link">{% if list.curation == 'open' or request.user == list.user %}{% trans "Add" %}{% else %}{% trans "Suggest" %}{% endif %}</button>
|
<div class="column ml-3">
|
||||||
</form>
|
<p>{% include 'snippets/book_titleby.html' with book=book %}</p>
|
||||||
</div>
|
|
||||||
</div>
|
<form
|
||||||
|
class="mt-1"
|
||||||
|
name="add-book"
|
||||||
|
method="post"
|
||||||
|
action="{% url 'list-add-book' %}{% if query %}?q={{ query }}{% endif %}"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="book" value="{{ book.id }}">
|
||||||
|
<input type="hidden" name="list" value="{{ list.id }}">
|
||||||
|
<button type="submit" class="button is-small is-link">{% if list.curation == 'open' or request.user == list.user %}{% trans "Add" %}{% else %}{% trans "Suggest" %}{% endif %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,11 +8,19 @@
|
||||||
<a href="{{ list.local_path }}">{{ list.name }}</a> <span class="subtitle">{% include 'snippets/privacy-icons.html' with item=list %}</span>
|
<a href="{{ list.local_path }}">{{ list.name }}</a> <span class="subtitle">{% include 'snippets/privacy-icons.html' with item=list %}</span>
|
||||||
</h4>
|
</h4>
|
||||||
</header>
|
</header>
|
||||||
<div class="card-image is-flex is-clipped">
|
|
||||||
{% for book in list.listitem_set.all|slice:5 %}
|
{% with list_books=list.listitem_set.all|slice:5 %}
|
||||||
<a href="{{ book.book.local_path }}">{% include 'snippets/book_cover.html' with book=book.book size="small" %}</a>
|
{% if list_books %}
|
||||||
{% endfor %}
|
<div class="card-image columns is-mobile is-gapless is-clipped">
|
||||||
</div>
|
{% for book in list_books %}
|
||||||
|
<a class="column is-cover" href="{{ book.book.local_path }}">
|
||||||
|
{% include 'snippets/book_cover.html' with book=book.book cover_class='is-h-s' aria='show' %}
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
<div class="card-content is-flex-grow-0">
|
<div class="card-content is-flex-grow-0">
|
||||||
<div {% if list.description %}title="{{ list.description }}"{% endif %}>
|
<div {% if list.description %}title="{{ list.description }}"{% endif %}>
|
||||||
{% if list.description %}
|
{% if list.description %}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if lists %}
|
{% if lists %}
|
||||||
<section class="block content">
|
<section class="block">
|
||||||
{% include 'lists/list_items.html' with lists=lists %}
|
{% include 'lists/list_items.html' with lists=lists %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
<form name="edit-profile" action="/change-password/" method="post" enctype="multipart/form-data">
|
<form name="edit-profile" action="{% url 'prefs-password' %}" method="post" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<label class="label" for="id_password">{% trans "New password:" %}</label>
|
<label class="label" for="id_password">{% trans "New password:" %}</label>
|
||||||
|
|
|
@ -11,10 +11,15 @@
|
||||||
|
|
||||||
<div class="block columns">
|
<div class="block columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h2 class="title">{% trans "Matching Books" %}</h2>
|
<h2 class="title is-4">{% trans "Matching Books" %}</h2>
|
||||||
<section class="block">
|
<section class="block">
|
||||||
{% if not local_results.results %}
|
{% if not local_results.results %}
|
||||||
<p>{% blocktrans %}No books found for "{{ query }}"{% endblocktrans %}</p>
|
<p><em>{% blocktrans %}No books found for "{{ query }}"{% endblocktrans %}</em></p>
|
||||||
|
{% if not user.is_authenticated %}
|
||||||
|
<p>
|
||||||
|
<a href="{% url 'login' %}">{% trans "Log in to import or add books." %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul>
|
<ul>
|
||||||
{% for result in local_results.results %}
|
{% for result in local_results.results %}
|
||||||
|
@ -29,39 +34,57 @@
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{% if book_results|slice:":1" and local_results.results %}
|
{% if book_results|slice:":1" and local_results.results %}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<p>
|
<h3 class="title is-6">
|
||||||
{% trans "Didn't find what you were looking for?" %}
|
{% trans "Didn't find what you were looking for?" %}
|
||||||
</p>
|
</h3>
|
||||||
{% trans "Show results from other catalogues" as button_text %}
|
{% trans "Show results from other catalogues" as button_text %}
|
||||||
{% include 'snippets/toggle/open_button.html' with text=button_text small=True controls_text="more-results" %}
|
{% include 'snippets/toggle/open_button.html' with text=button_text small=True controls_text="more-results" %}
|
||||||
|
|
||||||
|
{% if local_results.results %}
|
||||||
|
{% trans "Hide results from other catalogues" as button_text %}
|
||||||
|
{% include 'snippets/toggle/close_button.html' with text=button_text small=True controls_text="more-results" %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="{% if local_results.results %}is-hidden{% endif %}" id="more-results">
|
<div class="{% if local_results.results %}is-hidden{% endif %}" id="more-results">
|
||||||
{% for result_set in book_results|slice:"1:" %}
|
{% for result_set in book_results|slice:"1:" %}
|
||||||
{% if result_set.results %}
|
{% if result_set.results %}
|
||||||
<section class="block">
|
<section class="box has-background-white-bis">
|
||||||
{% if not result_set.connector.local %}
|
{% if not result_set.connector.local %}
|
||||||
<h3 class="title is-5">
|
<header class="columns is-mobile">
|
||||||
Results from <a href="{{ result_set.connector.base_url }}" target="_blank">{% if result_set.connector.name %}{{ result_set.connector.name }}{% else %}{{ result_set.connector.identifier }}{% endif %}</a>
|
<div class="column">
|
||||||
</h3>
|
<h3 class="title is-5">
|
||||||
|
Results from
|
||||||
|
<a href="{{ result_set.connector.base_url }}" target="_blank">{{ result_set.connector.name|default:result_set.connector.identifier }}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="column is-narrow">
|
||||||
|
{% trans "Show" as button_text %}
|
||||||
|
{% include 'snippets/toggle/open_button.html' with text=button_text small=True controls_text="more-results-panel" controls_uid=result_set.connector.identifier class="is-small" icon="arrow-down" pressed=forloop.first %}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<ul>
|
<div class="box has-background-white is-shadowless{% if not forloop.first %} is-hidden{% endif %}" id="more-results-panel-{{ result_set.connector.identifier }}">
|
||||||
{% for result in result_set.results %}
|
<div class="is-flex is-flex-direction-row-reverse">
|
||||||
<li class="pb-4">
|
<div>
|
||||||
{% include 'snippets/search_result_text.html' with result=result remote_result=True %}
|
{% trans "Close" as button_text %}
|
||||||
</li>
|
{% include 'snippets/toggle/toggle_button.html' with label=button_text class="delete" nonbutton=True controls_text="more-results-panel" controls_uid=result_set.connector.identifier pressed=forloop.first %}
|
||||||
{% endfor %}
|
</div>
|
||||||
</ul>
|
|
||||||
|
<ul class="is-flex-grow-1">
|
||||||
|
{% for result in result_set.results %}
|
||||||
|
<li class="mb-5">
|
||||||
|
{% include 'snippets/search_result_text.html' with result=result remote_result=True %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if local_results.results %}
|
|
||||||
{% trans "Hide results from other catalogues" as button_text %}
|
|
||||||
{% include 'snippets/toggle/close_button.html' with text=button_text small=True controls_text="more-results" %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block">
|
<div class="block">
|
||||||
|
@ -70,10 +93,11 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<section class="block">
|
{% if request.user.is_authenticated %}
|
||||||
<h2 class="title">{% trans "Matching Users" %}</h2>
|
<section class="box">
|
||||||
|
<h2 class="title is-4">{% trans "Matching Users" %}</h2>
|
||||||
{% if not user_results %}
|
{% if not user_results %}
|
||||||
<p>{% blocktrans %}No users found for "{{ query }}"{% endblocktrans %}</p>
|
<p><em>{% blocktrans %}No users found for "{{ query }}"{% endblocktrans %}</em></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ul>
|
<ul>
|
||||||
{% for result in user_results %}
|
{% for result in user_results %}
|
||||||
|
@ -87,10 +111,11 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section class="block">
|
{% endif %}
|
||||||
<h2 class="title">{% trans "Lists" %}</h2>
|
<section class="box">
|
||||||
|
<h2 class="title is-4">{% trans "Lists" %}</h2>
|
||||||
{% if not list_results %}
|
{% if not list_results %}
|
||||||
<p>{% blocktrans %}No lists found for "{{ query }}"{% endblocktrans %}</p>
|
<p><em>{% blocktrans %}No lists found for "{{ query }}"{% endblocktrans %}</em></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for result in list_results %}
|
{% for result in list_results %}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
|
|
|
@ -3,27 +3,44 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load bookwyrm_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
<div class="cover-container is-{{ size }}">
|
<figure
|
||||||
{% if book.cover %}
|
class="
|
||||||
<img
|
cover-container
|
||||||
class="book-cover"
|
{{ cover_class }}
|
||||||
src="/images/{{ book.cover }}"
|
|
||||||
alt="{{ book.alt_text }}"
|
|
||||||
title="{{ book.alt_text }}"
|
|
||||||
itemprop="thumbnailUrl"
|
|
||||||
>
|
|
||||||
{% else %}
|
|
||||||
<div class="no-cover book-cover">
|
|
||||||
<img
|
|
||||||
class="book-cover"
|
|
||||||
src="/static/images/no_cover.jpg"
|
|
||||||
alt="{% trans "No cover" %}"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div>
|
{% if not book.cover %}
|
||||||
<p>{{ book.alt_text }}</p>
|
no-cover
|
||||||
</div>
|
{% endif %}
|
||||||
</div>
|
"
|
||||||
|
|
||||||
|
{% if aria != "show" %}
|
||||||
|
aria-hidden="true"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
|
{% if book.alt_text %}
|
||||||
|
title="{{ book.alt_text }}"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="book-cover"
|
||||||
|
|
||||||
|
{% if book.cover %}
|
||||||
|
src="{% if img_path is None %}/images/{% else %}{{ img_path }}{% endif %}{{ book.cover }}"
|
||||||
|
itemprop="thumbnailUrl"
|
||||||
|
|
||||||
|
{% if book.alt_text %}
|
||||||
|
alt="{{ book.alt_text }}"
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
src="/static/images/no_cover.jpg"
|
||||||
|
alt="{% trans "No cover" %}"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
|
||||||
|
{% if not book.cover and book.alt_text %}
|
||||||
|
<figcaption class="cover_caption">
|
||||||
|
<p>{{ book.alt_text }}</p>
|
||||||
|
</figcaption>
|
||||||
|
{% endif %}
|
||||||
|
</figure>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
<div class="columns is-multiline">
|
<div class="columns is-mobile is-multiline">
|
||||||
{% for book in books %}
|
{% for book in books %}
|
||||||
<div class="column is-narrow">
|
<div class="column is-narrow">
|
||||||
<div class="box">
|
<div class="box is-flex is-flex-direction-column is-align-items-center">
|
||||||
<a href="/book/{{ book.id }}">
|
<div class="mb-3">
|
||||||
{% include 'snippets/book_cover.html' with book=book %}
|
<a href="/book/{{ book.id }}">
|
||||||
</a>
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-w-l-mobile is-h-l-mobile is-w-l-tablet is-h-xl-tablet' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
|
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,34 +1,41 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="columns is-mobile">
|
<div class="columns is-mobile is-gapless">
|
||||||
<div class="cover-container is-small column is-2">
|
<div class="column is-cover">
|
||||||
{% if result.cover %}
|
{% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' img_path=false %}
|
||||||
<img src="{{ result.cover }}" class="book-cover" aria-hidden="true">
|
|
||||||
{% else %}
|
|
||||||
<div class="no-cover book-cover">
|
|
||||||
<img class="book-cover" src="/static/images/no_cover.jpg" aria-hidden="true">
|
|
||||||
<div>
|
|
||||||
<p>{% trans "No cover" %}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column">
|
<div class="column is-10 ml-3">
|
||||||
<p>
|
<p>
|
||||||
<strong>
|
<strong>
|
||||||
<a href="{{ result.key }}"{% if remote_result %} rel=”noopener” target="_blank"{% endif %}>{{ result.title }}</a>
|
<a
|
||||||
|
href="{{ result.view_link|default:result.key }}"
|
||||||
|
{% if remote_result %}
|
||||||
|
rel=”noopener”
|
||||||
|
target="_blank"
|
||||||
|
{% endif %}
|
||||||
|
>{{ result.title }}</a>
|
||||||
</strong>
|
</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
{% if result.author %}
|
{% if result.author %}
|
||||||
{% blocktrans with author=result.author %}by {{ author }}{% endblocktrans %}{% endif %}{% if result.year %} ({{ result.year }})
|
{{ result.author }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if result.year %}
|
||||||
|
({{ result.year }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if remote_result %}
|
{% if remote_result %}
|
||||||
<form action="/resolve-book" method="POST">
|
<form class="mt-1" action="/resolve-book" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="remote_id" value="{{ result.key }}">
|
|
||||||
<button type="submit" class="button is-small is-link">{% trans "Import book" %}</button>
|
<input type="hidden" name="remote_id" value="{{ result.key }}">
|
||||||
</form>
|
|
||||||
|
<button type="submit" class="button is-small is-link">
|
||||||
|
{% trans "Import book" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,27 +10,30 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns is-gapless">
|
||||||
{% if not hide_book %}
|
{% if not hide_book %}
|
||||||
{% with book=status.book|default:status.mention_books.first %}
|
{% with book=status.book|default:status.mention_books.first %}
|
||||||
{% if book %}
|
{% if book %}
|
||||||
<div class="column is-narrow">
|
<div class="column is-cover">
|
||||||
<div class="columns is-mobile">
|
<div class="columns is-mobile is-gapless">
|
||||||
<div class="column is-narrow">
|
<div class="column is-cover">
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
|
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-mobile is-h-l-tablet' %}</a>
|
||||||
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
|
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
|
||||||
</div>
|
|
||||||
<div class="column is-hidden-tablet">
|
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
|
||||||
<p>{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:15 }}</p>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<div class="column ml-3-mobile is-hidden-tablet">
|
||||||
</div>
|
<p>{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:15 }}</p>
|
||||||
{% endif %}
|
</div>
|
||||||
{% endwith %}
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<article class="column">
|
<article class="column ml-3-tablet my-3-mobile">
|
||||||
{% if status_type == 'Review' %}
|
{% if status_type == 'Review' %}
|
||||||
<header class="mb-2">
|
<header class="mb-2">
|
||||||
<h3
|
<h3
|
||||||
|
|
|
@ -4,20 +4,25 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% if not hide_book %}
|
{% if not hide_book %}
|
||||||
{% with book=status.book|default:status.mention_books.first %}
|
{% with book=status.book|default:status.mention_books.first %}
|
||||||
<div class="columns is-mobile">
|
<div class="columns is-mobile is-gapless">
|
||||||
<div class="column is-narrow">
|
<a class="column is-cover is-narrow" href="{{ book.local_path }}">
|
||||||
<div>
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-xs is-h-s-tablet' %}
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
|
</a>
|
||||||
|
|
||||||
|
<div class="column ml-3">
|
||||||
|
<h3 class="title is-6 mb-1">
|
||||||
|
{% include 'snippets/book_titleby.html' with book=book %}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:20 }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endwith %}
|
||||||
<div class="column">
|
|
||||||
<h3 class="title is-6 mb-1">{% include 'snippets/book_titleby.html' with book=book %}</h3>
|
|
||||||
<p>{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:20 }}</p>
|
|
||||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<tr class="book-preview">
|
<tr class="book-preview">
|
||||||
<td class="book-preview-top-row">
|
<td class="book-preview-top-row">
|
||||||
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
|
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-tablet is-h-s' %}</a>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="{% trans "Title" %}">
|
<td data-title="{% trans "Title" %}">
|
||||||
<a href="{{ book.local_path }}">{{ book.title }}</a>
|
<a href="{{ book.local_path }}">{{ book.title }}</a>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
{% for book in shelf.books %}
|
{% for book in shelf.books %}
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a href="{{ book.local_path }}">
|
<a href="{{ book.local_path }}">
|
||||||
{% include 'snippets/book_cover.html' with book=book size="medium" %}
|
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m is-h-s-mobile' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -17,8 +17,6 @@ class ConnectorManager(TestCase):
|
||||||
self.edition = models.Edition.objects.create(
|
self.edition = models.Edition.objects.create(
|
||||||
title="Example Edition", parent_work=self.work, isbn_10="0000000000"
|
title="Example Edition", parent_work=self.work, isbn_10="0000000000"
|
||||||
)
|
)
|
||||||
self.work.default_edition = self.edition
|
|
||||||
self.work.save()
|
|
||||||
|
|
||||||
self.connector = models.Connector.objects.create(
|
self.connector = models.Connector.objects.create(
|
||||||
identifier="test_connector",
|
identifier="test_connector",
|
||||||
|
|
158
bookwyrm/tests/connectors/test_inventaire_connector.py
Normal file
158
bookwyrm/tests/connectors/test_inventaire_connector.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
""" testing book data connectors """
|
||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
from django.test import TestCase
|
||||||
|
import responses
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.connectors.inventaire import Connector
|
||||||
|
|
||||||
|
|
||||||
|
class Inventaire(TestCase):
|
||||||
|
"""test loading data from inventaire.io"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""creates the connector we'll use"""
|
||||||
|
models.Connector.objects.create(
|
||||||
|
identifier="inventaire.io",
|
||||||
|
name="Inventaire",
|
||||||
|
connector_file="inventaire",
|
||||||
|
base_url="https://inventaire.io",
|
||||||
|
books_url="https://inventaire.io",
|
||||||
|
covers_url="https://covers.inventaire.io",
|
||||||
|
search_url="https://inventaire.io/search?q=",
|
||||||
|
isbn_search_url="https://inventaire.io/isbn",
|
||||||
|
)
|
||||||
|
self.connector = Connector("inventaire.io")
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_book_data(self):
|
||||||
|
"""flattens the default structure to make it easier to parse"""
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://test.url/ok",
|
||||||
|
json={
|
||||||
|
"entities": {
|
||||||
|
"isbn:9780375757853": {
|
||||||
|
"claims": {
|
||||||
|
"wdt:P31": ["wd:Q3331189"],
|
||||||
|
},
|
||||||
|
"uri": "isbn:9780375757853",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirects": {},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = self.connector.get_book_data("https://test.url/ok")
|
||||||
|
self.assertEqual(result["wdt:P31"], ["wd:Q3331189"])
|
||||||
|
self.assertEqual(result["uri"], "isbn:9780375757853")
|
||||||
|
|
||||||
|
def test_format_search_result(self):
|
||||||
|
"""json to search result objs"""
|
||||||
|
search_file = pathlib.Path(__file__).parent.joinpath(
|
||||||
|
"../data/inventaire_search.json"
|
||||||
|
)
|
||||||
|
search_results = json.loads(search_file.read_bytes())
|
||||||
|
|
||||||
|
results = self.connector.parse_search_data(search_results)
|
||||||
|
formatted = self.connector.format_search_result(results[0])
|
||||||
|
|
||||||
|
self.assertEqual(formatted.title, "The Stories of Vladimir Nabokov")
|
||||||
|
self.assertEqual(
|
||||||
|
formatted.key, "https://inventaire.io?action=by-uris&uris=wd:Q7766679"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
formatted.cover,
|
||||||
|
"https://covers.inventaire.io/img/entities/ddb32e115a28dcc0465023869ba19f6868ec4042",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_cover_url(self):
|
||||||
|
"""figure out where the cover image is"""
|
||||||
|
cover_blob = {"url": "/img/entities/d46a8"}
|
||||||
|
result = self.connector.get_cover_url(cover_blob)
|
||||||
|
self.assertEqual(result, "https://covers.inventaire.io/img/entities/d46a8")
|
||||||
|
|
||||||
|
cover_blob = {
|
||||||
|
"url": "https://commons.wikimedia.org/wiki/Special:FilePath/The%20Moonstone%201st%20ed.jpg?width=1000",
|
||||||
|
"file": "The Moonstone 1st ed.jpg",
|
||||||
|
"credits": {
|
||||||
|
"text": "Wikimedia Commons",
|
||||||
|
"url": "https://commons.wikimedia.org/wiki/File:The Moonstone 1st ed.jpg",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.connector.get_cover_url(cover_blob)
|
||||||
|
self.assertEqual(
|
||||||
|
result,
|
||||||
|
"https://commons.wikimedia.org/wiki/Special:FilePath/The%20Moonstone%201st%20ed.jpg?width=1000",
|
||||||
|
)
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_resolve_keys(self):
|
||||||
|
"""makes an http request"""
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://inventaire.io?action=by-uris&uris=wd:Q465821",
|
||||||
|
json={
|
||||||
|
"entities": {
|
||||||
|
"wd:Q465821": {
|
||||||
|
"type": "genre",
|
||||||
|
"labels": {
|
||||||
|
"nl": "briefroman",
|
||||||
|
"en": "epistolary novel",
|
||||||
|
"de-ch": "Briefroman",
|
||||||
|
"en-ca": "Epistolary novel",
|
||||||
|
"nb": "brev- og dagbokroman",
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"en": "novel written as a series of documents",
|
||||||
|
"es": "novela escrita como una serie de documentos",
|
||||||
|
"eo": "romano en la formo de serio de leteroj",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"redirects": {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://inventaire.io?action=by-uris&uris=wd:Q208505",
|
||||||
|
json={
|
||||||
|
"entities": {
|
||||||
|
"wd:Q208505": {
|
||||||
|
"type": "genre",
|
||||||
|
"labels": {
|
||||||
|
"en": "crime novel",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
keys = [
|
||||||
|
"wd:Q465821",
|
||||||
|
"wd:Q208505",
|
||||||
|
]
|
||||||
|
result = self.connector.resolve_keys(keys)
|
||||||
|
self.assertEqual(result, ["epistolary novel", "crime novel"])
|
||||||
|
|
||||||
|
def test_isbn_search(self):
|
||||||
|
"""another search type"""
|
||||||
|
search_file = pathlib.Path(__file__).parent.joinpath(
|
||||||
|
"../data/inventaire_isbn_search.json"
|
||||||
|
)
|
||||||
|
search_results = json.loads(search_file.read_bytes())
|
||||||
|
|
||||||
|
results = self.connector.parse_isbn_search_data(search_results)
|
||||||
|
formatted = self.connector.format_isbn_search_result(results[0])
|
||||||
|
|
||||||
|
self.assertEqual(formatted.title, "L'homme aux cercles bleus")
|
||||||
|
self.assertEqual(
|
||||||
|
formatted.key,
|
||||||
|
"https://inventaire.io?action=by-uris&uris=isbn:9782290349229",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
formatted.cover,
|
||||||
|
"https://covers.inventaire.io/img/entities/12345",
|
||||||
|
)
|
|
@ -84,11 +84,11 @@ class SelfConnector(TestCase):
|
||||||
title="Edition 1 Title", parent_work=work
|
title="Edition 1 Title", parent_work=work
|
||||||
)
|
)
|
||||||
edition_2 = models.Edition.objects.create(
|
edition_2 = models.Edition.objects.create(
|
||||||
title="Edition 2 Title", parent_work=work
|
title="Edition 2 Title",
|
||||||
|
parent_work=work,
|
||||||
|
edition_rank=20, # that's default babey
|
||||||
)
|
)
|
||||||
edition_3 = models.Edition.objects.create(title="Fish", parent_work=work)
|
edition_3 = models.Edition.objects.create(title="Fish", parent_work=work)
|
||||||
work.default_edition = edition_2
|
|
||||||
work.save()
|
|
||||||
|
|
||||||
# pick the best edition
|
# pick the best edition
|
||||||
results = self.connector.search("Edition 1 Title")
|
results = self.connector.search("Edition 1 Title")
|
||||||
|
|
45
bookwyrm/tests/data/inventaire_edition.json
Normal file
45
bookwyrm/tests/data/inventaire_edition.json
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"entities": {
|
||||||
|
"isbn:9780375757853": {
|
||||||
|
"_id": "7beee121a8d9ac345cdf4e9128577723",
|
||||||
|
"_rev": "2-ac318b04b953ca3894deb77fee28211c",
|
||||||
|
"type": "edition",
|
||||||
|
"labels": {},
|
||||||
|
"claims": {
|
||||||
|
"wdt:P31": [
|
||||||
|
"wd:Q3331189"
|
||||||
|
],
|
||||||
|
"wdt:P212": [
|
||||||
|
"978-0-375-75785-3"
|
||||||
|
],
|
||||||
|
"wdt:P957": [
|
||||||
|
"0-375-75785-6"
|
||||||
|
],
|
||||||
|
"wdt:P407": [
|
||||||
|
"wd:Q1860"
|
||||||
|
],
|
||||||
|
"wdt:P1476": [
|
||||||
|
"The Moonstone"
|
||||||
|
],
|
||||||
|
"wdt:P577": [
|
||||||
|
"2001"
|
||||||
|
],
|
||||||
|
"wdt:P629": [
|
||||||
|
"wd:Q2362563"
|
||||||
|
],
|
||||||
|
"invp:P2": [
|
||||||
|
"d46a8eac7555afa479b8bbb5149f35858e8e19c4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"created": 1495452670475,
|
||||||
|
"updated": 1541032981834,
|
||||||
|
"version": 3,
|
||||||
|
"uri": "isbn:9780375757853",
|
||||||
|
"originalLang": "en",
|
||||||
|
"image": {
|
||||||
|
"url": "/img/entities/d46a8eac7555afa479b8bbb5149f35858e8e19c4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirects": {}
|
||||||
|
}
|
48
bookwyrm/tests/data/inventaire_isbn_search.json
Normal file
48
bookwyrm/tests/data/inventaire_isbn_search.json
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"entities": {
|
||||||
|
"isbn:9782290349229": {
|
||||||
|
"_id": "d59e3e64f92c6340fbb10c5dcf7c0abf",
|
||||||
|
"_rev": "3-079ed51158a001dc74caafb21cff1c22",
|
||||||
|
"type": "edition",
|
||||||
|
"labels": {},
|
||||||
|
"claims": {
|
||||||
|
"wdt:P31": [
|
||||||
|
"wd:Q3331189"
|
||||||
|
],
|
||||||
|
"wdt:P212": [
|
||||||
|
"978-2-290-34922-9"
|
||||||
|
],
|
||||||
|
"wdt:P957": [
|
||||||
|
"2-290-34922-4"
|
||||||
|
],
|
||||||
|
"wdt:P407": [
|
||||||
|
"wd:Q150"
|
||||||
|
],
|
||||||
|
"wdt:P1476": [
|
||||||
|
"L'homme aux cercles bleus"
|
||||||
|
],
|
||||||
|
"wdt:P629": [
|
||||||
|
"wd:Q3203603"
|
||||||
|
],
|
||||||
|
"wdt:P123": [
|
||||||
|
"wd:Q3156592"
|
||||||
|
],
|
||||||
|
"invp:P2": [
|
||||||
|
"57883743aa7c6ad25885a63e6e94349ec4f71562"
|
||||||
|
],
|
||||||
|
"wdt:P577": [
|
||||||
|
"2005-05-01"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"created": 1485023383338,
|
||||||
|
"updated": 1609171008418,
|
||||||
|
"version": 5,
|
||||||
|
"uri": "isbn:9782290349229",
|
||||||
|
"originalLang": "fr",
|
||||||
|
"image": {
|
||||||
|
"url": "/img/entities/12345"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirects": {}
|
||||||
|
}
|
111
bookwyrm/tests/data/inventaire_search.json
Normal file
111
bookwyrm/tests/data/inventaire_search.json
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
{
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"id": "Q7766679",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q7766679",
|
||||||
|
"label": "The Stories of Vladimir Nabokov",
|
||||||
|
"description": "book by Vladimir Nabokov",
|
||||||
|
"image": [
|
||||||
|
"ddb32e115a28dcc0465023869ba19f6868ec4042"
|
||||||
|
],
|
||||||
|
"_score": 25.180836,
|
||||||
|
"_popularity": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q47407212",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q47407212",
|
||||||
|
"label": "Conversations with Vladimir Nabokov",
|
||||||
|
"description": "book edited by Robert Golla",
|
||||||
|
"image": [],
|
||||||
|
"_score": 24.41498,
|
||||||
|
"_popularity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q6956987",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q6956987",
|
||||||
|
"label": "Nabokov's Congeries",
|
||||||
|
"description": "book by Vladimir Nabokov",
|
||||||
|
"image": [],
|
||||||
|
"_score": 22.343866,
|
||||||
|
"_popularity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q6956986",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q6956986",
|
||||||
|
"label": "Nabokov's Butterflies",
|
||||||
|
"description": "book by Brian Boyd",
|
||||||
|
"image": [],
|
||||||
|
"_score": 22.343866,
|
||||||
|
"_popularity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q47472170",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q47472170",
|
||||||
|
"label": "A Reader's Guide to Nabokov's \"Lolita\"",
|
||||||
|
"description": "book by Julian W. Connolly",
|
||||||
|
"image": [],
|
||||||
|
"_score": 19.482553,
|
||||||
|
"_popularity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q7936323",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q7936323",
|
||||||
|
"label": "Visiting Mrs Nabokov: And Other Excursions",
|
||||||
|
"description": "book by Martin Amis",
|
||||||
|
"image": [],
|
||||||
|
"_score": 18.684965,
|
||||||
|
"_popularity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1732d81bf7376e04da27568a778561a4",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "inv:1732d81bf7376e04da27568a778561a4",
|
||||||
|
"label": "Nabokov's Dark Cinema",
|
||||||
|
"image": [
|
||||||
|
"7512805a53da569b11bf29cc3fb272c969619749"
|
||||||
|
],
|
||||||
|
"_score": 16.56681,
|
||||||
|
"_popularity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "00f118336b02219e1bddc8fa93c56050",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "inv:00f118336b02219e1bddc8fa93c56050",
|
||||||
|
"label": "The Cambridge Companion to Nabokov",
|
||||||
|
"image": [
|
||||||
|
"0683a059fb95430cfa73334f9eff2ef377f3ae3d"
|
||||||
|
],
|
||||||
|
"_score": 15.502292,
|
||||||
|
"_popularity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6e59f968a1cd00dbedeb1964dec47507",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "inv:6e59f968a1cd00dbedeb1964dec47507",
|
||||||
|
"label": "Vladimir Nabokov : selected letters, 1940-1977",
|
||||||
|
"image": [
|
||||||
|
"e3ce8c0ee89d576adf2651a6e5ce55fc6d9f8cb3"
|
||||||
|
],
|
||||||
|
"_score": 15.019735,
|
||||||
|
"_popularity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Q127149",
|
||||||
|
"type": "works",
|
||||||
|
"uri": "wd:Q127149",
|
||||||
|
"label": "Lolita",
|
||||||
|
"description": "novel by Vladimir Nabokov",
|
||||||
|
"image": [
|
||||||
|
"51cbfdbf7257b1a6bb3ea3fbb167dbce1fb44a0e"
|
||||||
|
],
|
||||||
|
"_score": 13.458428,
|
||||||
|
"_popularity": 32
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
155
bookwyrm/tests/data/inventaire_work.json
Normal file
155
bookwyrm/tests/data/inventaire_work.json
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
{
|
||||||
|
"entities": {
|
||||||
|
"wd:Q2362563": {
|
||||||
|
"type": "work",
|
||||||
|
"labels": {
|
||||||
|
"zh-hans": "月亮宝石",
|
||||||
|
"zh-hant": "月亮寶石",
|
||||||
|
"zh-hk": "月光石",
|
||||||
|
"zh-tw": "月光石",
|
||||||
|
"cy": "The Moonstone",
|
||||||
|
"ml": "ദ മൂൺസ്റ്റോൺ",
|
||||||
|
"ja": "月長石",
|
||||||
|
"te": "ది మూన్ స్టోన్",
|
||||||
|
"ru": "Лунный камень",
|
||||||
|
"fr": "La Pierre de lune",
|
||||||
|
"en": "The Moonstone",
|
||||||
|
"es": "La piedra lunar",
|
||||||
|
"it": "La Pietra di Luna",
|
||||||
|
"zh": "月亮宝石",
|
||||||
|
"pl": "Kamień Księżycowy",
|
||||||
|
"sr": "2 Јн",
|
||||||
|
"ta": "moon stone",
|
||||||
|
"ar": "حجر القمر",
|
||||||
|
"fa": "ماهالماس",
|
||||||
|
"uk": "Місячний камінь",
|
||||||
|
"nl": "The Moonstone",
|
||||||
|
"de": "Der Monddiamant",
|
||||||
|
"sl": "Diamant",
|
||||||
|
"sv": "Månstenen",
|
||||||
|
"he": "אבן הירח",
|
||||||
|
"eu": "Ilargi-harriak",
|
||||||
|
"bg": "Лунният камък",
|
||||||
|
"ka": "მთვარის ქვა",
|
||||||
|
"eo": "La Lunŝtono",
|
||||||
|
"hy": "Լուսնաքար",
|
||||||
|
"ro": "Piatra Lunii",
|
||||||
|
"ca": "The Moonstone",
|
||||||
|
"is": "The Moonstone"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"it": "romanzo scritto da Wilkie Collins",
|
||||||
|
"en": "novel by Wilkie Collins",
|
||||||
|
"de": "Buch von Wilkie Collins",
|
||||||
|
"nl": "boek van Wilkie Collins",
|
||||||
|
"ru": "роман Уилки Коллинза",
|
||||||
|
"he": "רומן מאת וילקי קולינס",
|
||||||
|
"ar": "رواية من تأليف ويلكي كولينز",
|
||||||
|
"fr": "livre de Wilkie Collins",
|
||||||
|
"es": "libro de Wilkie Collins",
|
||||||
|
"bg": "роман на Уилки Колинс",
|
||||||
|
"ka": "უილკი კოლინსის რომანი",
|
||||||
|
"eo": "angalingva romano far Wilkie Collins",
|
||||||
|
"ro": "roman de Wilkie Collins"
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"zh": [
|
||||||
|
"月光石"
|
||||||
|
],
|
||||||
|
"ml": [
|
||||||
|
"The Moonstone"
|
||||||
|
],
|
||||||
|
"fr": [
|
||||||
|
"The Moonstone"
|
||||||
|
],
|
||||||
|
"it": [
|
||||||
|
"Il diamante indiano",
|
||||||
|
"La pietra della luna",
|
||||||
|
"La maledizione del diamante indiano"
|
||||||
|
],
|
||||||
|
"ro": [
|
||||||
|
"The Moonstone"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"claims": {
|
||||||
|
"wdt:P18": [
|
||||||
|
"The Moonstone 1st ed.jpg"
|
||||||
|
],
|
||||||
|
"wdt:P31": [
|
||||||
|
"wd:Q7725634"
|
||||||
|
],
|
||||||
|
"wdt:P50": [
|
||||||
|
"wd:Q210740"
|
||||||
|
],
|
||||||
|
"wdt:P123": [
|
||||||
|
"wd:Q4457856"
|
||||||
|
],
|
||||||
|
"wdt:P136": [
|
||||||
|
"wd:Q465821",
|
||||||
|
"wd:Q208505",
|
||||||
|
"wd:Q10992055"
|
||||||
|
],
|
||||||
|
"wdt:P156": [
|
||||||
|
"wd:Q7228798"
|
||||||
|
],
|
||||||
|
"wdt:P268": [
|
||||||
|
"12496407z"
|
||||||
|
],
|
||||||
|
"wdt:P407": [
|
||||||
|
"wd:Q7979"
|
||||||
|
],
|
||||||
|
"wdt:P577": [
|
||||||
|
"1868"
|
||||||
|
],
|
||||||
|
"wdt:P1433": [
|
||||||
|
"wd:Q21"
|
||||||
|
],
|
||||||
|
"wdt:P1476": [
|
||||||
|
"The Moonstone"
|
||||||
|
],
|
||||||
|
"wdt:P1680": [
|
||||||
|
"A Romance"
|
||||||
|
],
|
||||||
|
"wdt:P2034": [
|
||||||
|
"155"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sitelinks": {
|
||||||
|
"arwiki": "حجر القمر (رواية)",
|
||||||
|
"bgwiki": "Лунният камък (роман)",
|
||||||
|
"cywiki": "The Moonstone",
|
||||||
|
"dewiki": "Der Monddiamant",
|
||||||
|
"enwiki": "The Moonstone",
|
||||||
|
"enwikisource": "The Moonstone",
|
||||||
|
"eswiki": "La piedra lunar",
|
||||||
|
"euwiki": "Ilargi-harria",
|
||||||
|
"fawiki": "ماهالماس",
|
||||||
|
"frwiki": "La Pierre de lune (roman de Wilkie Collins)",
|
||||||
|
"hewiki": "אבן הירח",
|
||||||
|
"hywiki": "Լուսնաքար",
|
||||||
|
"iswiki": "The Moonstone",
|
||||||
|
"itwiki": "La pietra di Luna",
|
||||||
|
"jawiki": "月長石 (小説)",
|
||||||
|
"mlwiki": "ദ മൂൺസ്റ്റോൺ",
|
||||||
|
"plwiki": "Kamień Księżycowy (powieść)",
|
||||||
|
"ruwiki": "Лунный камень (роман)",
|
||||||
|
"slwiki": "Diamant (roman)",
|
||||||
|
"srwikisource": "Нови завјет (Караџић) / 2. Јованова",
|
||||||
|
"svwiki": "Månstenen",
|
||||||
|
"tewiki": "ది మూన్స్టోన్",
|
||||||
|
"ukwiki": "Місячний камінь (роман)",
|
||||||
|
"zhwiki": "月亮宝石"
|
||||||
|
},
|
||||||
|
"uri": "wd:Q2362563",
|
||||||
|
"image": {
|
||||||
|
"url": "https://commons.wikimedia.org/wiki/Special:FilePath/The%20Moonstone%201st%20ed.jpg?width=1000",
|
||||||
|
"file": "The Moonstone 1st ed.jpg",
|
||||||
|
"credits": {
|
||||||
|
"text": "Wikimedia Commons",
|
||||||
|
"url": "https://commons.wikimedia.org/wiki/File:The Moonstone 1st ed.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirects": {}
|
||||||
|
}
|
|
@ -26,20 +26,23 @@ class BaseModel(TestCase):
|
||||||
outbox="https://example.com/users/rat/outbox",
|
outbox="https://example.com/users/rat/outbox",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class BookWyrmTestModel(base_model.BookWyrmModel):
|
||||||
|
"""just making it not abstract"""
|
||||||
|
|
||||||
|
self.test_model = BookWyrmTestModel()
|
||||||
|
|
||||||
def test_remote_id(self):
|
def test_remote_id(self):
|
||||||
"""these should be generated"""
|
"""these should be generated"""
|
||||||
instance = base_model.BookWyrmModel()
|
self.test_model.id = 1
|
||||||
instance.id = 1
|
expected = self.test_model.get_remote_id()
|
||||||
expected = instance.get_remote_id()
|
self.assertEqual(expected, "https://%s/bookwyrmtestmodel/1" % DOMAIN)
|
||||||
self.assertEqual(expected, "https://%s/bookwyrmmodel/1" % DOMAIN)
|
|
||||||
|
|
||||||
def test_remote_id_with_user(self):
|
def test_remote_id_with_user(self):
|
||||||
"""format of remote id when there's a user object"""
|
"""format of remote id when there's a user object"""
|
||||||
instance = base_model.BookWyrmModel()
|
self.test_model.user = self.local_user
|
||||||
instance.user = self.local_user
|
self.test_model.id = 1
|
||||||
instance.id = 1
|
expected = self.test_model.get_remote_id()
|
||||||
expected = instance.get_remote_id()
|
self.assertEqual(expected, "https://%s/user/mouse/bookwyrmtestmodel/1" % DOMAIN)
|
||||||
self.assertEqual(expected, "https://%s/user/mouse/bookwyrmmodel/1" % DOMAIN)
|
|
||||||
|
|
||||||
def test_set_remote_id(self):
|
def test_set_remote_id(self):
|
||||||
"""this function sets remote ids after creation"""
|
"""this function sets remote ids after creation"""
|
||||||
|
|
|
@ -84,9 +84,3 @@ class Book(TestCase):
|
||||||
self.first_edition.description = "hi"
|
self.first_edition.description = "hi"
|
||||||
self.first_edition.save()
|
self.first_edition.save()
|
||||||
self.assertEqual(self.first_edition.edition_rank, 1)
|
self.assertEqual(self.first_edition.edition_rank, 1)
|
||||||
|
|
||||||
# default edition
|
|
||||||
self.work.default_edition = self.first_edition
|
|
||||||
self.work.save()
|
|
||||||
self.first_edition.refresh_from_db()
|
|
||||||
self.assertEqual(self.first_edition.edition_rank, 20)
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from bookwyrm import models, settings
|
from bookwyrm import models
|
||||||
|
|
||||||
|
|
||||||
class ReadThrough(TestCase):
|
class ReadThrough(TestCase):
|
||||||
|
@ -19,8 +19,6 @@ class ReadThrough(TestCase):
|
||||||
self.edition = models.Edition.objects.create(
|
self.edition = models.Edition.objects.create(
|
||||||
title="Example Edition", parent_work=self.work
|
title="Example Edition", parent_work=self.work
|
||||||
)
|
)
|
||||||
self.work.default_edition = self.edition
|
|
||||||
self.work.save()
|
|
||||||
|
|
||||||
self.readthrough = models.ReadThrough.objects.create(
|
self.readthrough = models.ReadThrough.objects.create(
|
||||||
user=self.user, book=self.edition
|
user=self.user, book=self.edition
|
||||||
|
|
|
@ -127,6 +127,43 @@ class InboxCreate(TestCase):
|
||||||
self.assertTrue(models.Notification.objects.filter(user=self.local_user))
|
self.assertTrue(models.Notification.objects.filter(user=self.local_user))
|
||||||
self.assertEqual(models.Notification.objects.get().notification_type, "REPLY")
|
self.assertEqual(models.Notification.objects.get().notification_type, "REPLY")
|
||||||
|
|
||||||
|
def test_create_rating(self):
|
||||||
|
"""a remote rating activity"""
|
||||||
|
book = models.Edition.objects.create(
|
||||||
|
title="Test Book", remote_id="https://example.com/book/1"
|
||||||
|
)
|
||||||
|
activity = self.create_json
|
||||||
|
activity["object"] = {
|
||||||
|
"id": "https://example.com/user/mouse/reviewrating/12",
|
||||||
|
"type": "Rating",
|
||||||
|
"published": "2021-04-29T21:27:30.014235+00:00",
|
||||||
|
"attributedTo": "https://example.com/user/mouse",
|
||||||
|
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
"cc": ["https://example.com/user/mouse/followers"],
|
||||||
|
"replies": {
|
||||||
|
"id": "https://example.com/user/mouse/reviewrating/12/replies",
|
||||||
|
"type": "OrderedCollection",
|
||||||
|
"totalItems": 0,
|
||||||
|
"first": "https://example.com/user/mouse/reviewrating/12/replies?page=1",
|
||||||
|
"last": "https://example.com/user/mouse/reviewrating/12/replies?page=1",
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
},
|
||||||
|
"inReplyTo": "",
|
||||||
|
"summary": "",
|
||||||
|
"tag": [],
|
||||||
|
"attachment": [],
|
||||||
|
"sensitive": False,
|
||||||
|
"inReplyToBook": "https://example.com/book/1",
|
||||||
|
"rating": 3,
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
}
|
||||||
|
with patch("bookwyrm.activitystreams.ActivityStream.add_status") as redis_mock:
|
||||||
|
views.inbox.activity_task(activity)
|
||||||
|
self.assertTrue(redis_mock.called)
|
||||||
|
rating = models.ReviewRating.objects.first()
|
||||||
|
self.assertEqual(rating.book, book)
|
||||||
|
self.assertEqual(rating.rating, 3.0)
|
||||||
|
|
||||||
def test_create_list(self):
|
def test_create_list(self):
|
||||||
"""a new list"""
|
"""a new list"""
|
||||||
activity = self.create_json
|
activity = self.create_json
|
||||||
|
|
|
@ -219,7 +219,7 @@ class ViewsHelpers(TestCase):
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
# 1 shared follow
|
# 1 shared follow
|
||||||
self.local_user.following.add(user_2)
|
self.local_user.following.add(user_2)
|
||||||
user_1.following.add(user_2)
|
user_1.followers.add(user_2)
|
||||||
|
|
||||||
# 1 shared book
|
# 1 shared book
|
||||||
models.ShelfBook.objects.create(
|
models.ShelfBook.objects.create(
|
||||||
|
@ -264,7 +264,7 @@ class ViewsHelpers(TestCase):
|
||||||
local=True,
|
local=True,
|
||||||
localname=i,
|
localname=i,
|
||||||
)
|
)
|
||||||
user.followers.add(user_1)
|
user.following.add(user_1)
|
||||||
user.followers.add(self.local_user)
|
user.followers.add(self.local_user)
|
||||||
|
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
|
|
|
@ -20,8 +20,6 @@ class ReadThrough(TestCase):
|
||||||
self.edition = models.Edition.objects.create(
|
self.edition = models.Edition.objects.create(
|
||||||
title="Example Edition", parent_work=self.work
|
title="Example Edition", parent_work=self.work
|
||||||
)
|
)
|
||||||
self.work.default_edition = self.edition
|
|
||||||
self.work.save()
|
|
||||||
|
|
||||||
self.user = models.User.objects.create_user(
|
self.user = models.User.objects.create_user(
|
||||||
"cinco", "cinco@example.com", "seissiete", local=True, localname="cinco"
|
"cinco", "cinco@example.com", "seissiete", local=True, localname="cinco"
|
||||||
|
|
|
@ -43,7 +43,7 @@ urlpatterns = [
|
||||||
re_path("^api/updates/notifications/?$", views.get_notification_count),
|
re_path("^api/updates/notifications/?$", views.get_notification_count),
|
||||||
re_path("^api/updates/stream/(?P<stream>[a-z]+)/?$", views.get_unread_status_count),
|
re_path("^api/updates/stream/(?P<stream>[a-z]+)/?$", views.get_unread_status_count),
|
||||||
# authentication
|
# authentication
|
||||||
re_path(r"^login/?$", views.Login.as_view()),
|
re_path(r"^login/?$", views.Login.as_view(), name="login"),
|
||||||
re_path(r"^register/?$", views.Register.as_view()),
|
re_path(r"^register/?$", views.Register.as_view()),
|
||||||
re_path(r"^logout/?$", views.Logout.as_view()),
|
re_path(r"^logout/?$", views.Logout.as_view()),
|
||||||
re_path(r"^password-reset/?$", views.PasswordResetRequest.as_view()),
|
re_path(r"^password-reset/?$", views.PasswordResetRequest.as_view()),
|
||||||
|
@ -224,7 +224,11 @@ urlpatterns = [
|
||||||
re_path(r"^hide-goal/?$", views.hide_goal, name="hide-goal"),
|
re_path(r"^hide-goal/?$", views.hide_goal, name="hide-goal"),
|
||||||
# preferences
|
# preferences
|
||||||
re_path(r"^preferences/profile/?$", views.EditUser.as_view(), name="prefs-profile"),
|
re_path(r"^preferences/profile/?$", views.EditUser.as_view(), name="prefs-profile"),
|
||||||
re_path(r"^preferences/password/?$", views.ChangePassword.as_view()),
|
re_path(
|
||||||
|
r"^preferences/password/?$",
|
||||||
|
views.ChangePassword.as_view(),
|
||||||
|
name="prefs-password",
|
||||||
|
),
|
||||||
re_path(r"^preferences/block/?$", views.Block.as_view()),
|
re_path(r"^preferences/block/?$", views.Block.as_view()),
|
||||||
re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()),
|
re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()),
|
||||||
re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock),
|
re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock),
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Author(View):
|
||||||
).distinct()
|
).distinct()
|
||||||
data = {
|
data = {
|
||||||
"author": author,
|
"author": author,
|
||||||
"books": [b.get_default_edition() for b in books],
|
"books": [b.default_edition for b in books],
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, "author.html", data)
|
return TemplateResponse(request, "author.html", data)
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Book(View):
|
||||||
return ActivitypubResponse(book.to_activity())
|
return ActivitypubResponse(book.to_activity())
|
||||||
|
|
||||||
if isinstance(book, models.Work):
|
if isinstance(book, models.Work):
|
||||||
book = book.get_default_edition()
|
book = book.default_edition
|
||||||
if not book or not book.parent_work:
|
if not book or not book.parent_work:
|
||||||
return HttpResponseNotFound()
|
return HttpResponseNotFound()
|
||||||
|
|
||||||
|
@ -156,7 +156,6 @@ class EditBook(View):
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
print(data["author_matches"])
|
|
||||||
|
|
||||||
# we're creating a new book
|
# we're creating a new book
|
||||||
if not book:
|
if not book:
|
||||||
|
|
|
@ -123,7 +123,7 @@ def get_edition(book_id):
|
||||||
"""look up a book in the db and return an edition"""
|
"""look up a book in the db and return an edition"""
|
||||||
book = models.Book.objects.select_subclasses().get(id=book_id)
|
book = models.Book.objects.select_subclasses().get(id=book_id)
|
||||||
if isinstance(book, models.Work):
|
if isinstance(book, models.Work):
|
||||||
book = book.get_default_edition()
|
book = book.default_edition
|
||||||
return book
|
return book
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,11 +190,11 @@ def get_annotated_users(user, *args, **kwargs):
|
||||||
.exclude(Q(id__in=user.blocks.all()) | Q(blocks=user))
|
.exclude(Q(id__in=user.blocks.all()) | Q(blocks=user))
|
||||||
.annotate(
|
.annotate(
|
||||||
mutuals=Count(
|
mutuals=Count(
|
||||||
"following",
|
"followers",
|
||||||
filter=Q(
|
filter=Q(
|
||||||
~Q(id=user.id),
|
~Q(id=user.id),
|
||||||
~Q(id__in=user.following.all()),
|
~Q(id__in=user.following.all()),
|
||||||
following__in=user.following.all(),
|
followers__in=user.following.all(),
|
||||||
),
|
),
|
||||||
distinct=True,
|
distinct=True,
|
||||||
),
|
),
|
||||||
|
|
|
@ -30,27 +30,30 @@ class Search(View):
|
||||||
)
|
)
|
||||||
return JsonResponse([r.json() for r in book_results], safe=False)
|
return JsonResponse([r.json() for r in book_results], safe=False)
|
||||||
|
|
||||||
|
data = {"query": query or ""}
|
||||||
|
|
||||||
# use webfinger for mastodon style account@domain.com username
|
# use webfinger for mastodon style account@domain.com username
|
||||||
if query and re.match(regex.full_username, query):
|
if query and re.match(regex.full_username, query):
|
||||||
handle_remote_webfinger(query)
|
handle_remote_webfinger(query)
|
||||||
|
|
||||||
# do a user search
|
# do a user search
|
||||||
user_results = (
|
if request.user.is_authenticated:
|
||||||
models.User.viewer_aware_objects(request.user)
|
data["user_results"] = (
|
||||||
.annotate(
|
models.User.viewer_aware_objects(request.user)
|
||||||
similarity=Greatest(
|
.annotate(
|
||||||
TrigramSimilarity("username", query),
|
similarity=Greatest(
|
||||||
TrigramSimilarity("localname", query),
|
TrigramSimilarity("username", query),
|
||||||
|
TrigramSimilarity("localname", query),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
.filter(
|
||||||
|
similarity__gt=0.5,
|
||||||
|
)
|
||||||
|
.order_by("-similarity")[:10]
|
||||||
)
|
)
|
||||||
.filter(
|
|
||||||
similarity__gt=0.5,
|
|
||||||
)
|
|
||||||
.order_by("-similarity")[:10]
|
|
||||||
)
|
|
||||||
|
|
||||||
# any relevent lists?
|
# any relevent lists?
|
||||||
list_results = (
|
data["list_results"] = (
|
||||||
privacy_filter(
|
privacy_filter(
|
||||||
request.user,
|
request.user,
|
||||||
models.List.objects,
|
models.List.objects,
|
||||||
|
@ -68,11 +71,7 @@ class Search(View):
|
||||||
.order_by("-similarity")[:10]
|
.order_by("-similarity")[:10]
|
||||||
)
|
)
|
||||||
|
|
||||||
book_results = connector_manager.search(query, min_confidence=min_confidence)
|
data["book_results"] = connector_manager.search(
|
||||||
data = {
|
query, min_confidence=min_confidence
|
||||||
"book_results": book_results,
|
)
|
||||||
"user_results": user_results,
|
|
||||||
"list_results": list_results,
|
|
||||||
"query": query or "",
|
|
||||||
}
|
|
||||||
return TemplateResponse(request, "search_results.html", data)
|
return TemplateResponse(request, "search_results.html", data)
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-26 09:56-0700\n"
|
"POT-Creation-Date: 2021-04-29 13:24-0700\n"
|
||||||
"PO-Revision-Date: 2021-03-02 17:19-0800\n"
|
"PO-Revision-Date: 2021-03-02 17:19-0800\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: English <LL@li.org>\n"
|
"Language-Team: English <LL@li.org>\n"
|
||||||
|
@ -100,23 +100,23 @@ msgstr "Username"
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr "Dieser Benutzename ist bereits vergeben."
|
msgstr "Dieser Benutzename ist bereits vergeben."
|
||||||
|
|
||||||
#: bookwyrm/settings.py:152
|
#: bookwyrm/settings.py:155
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Englisch"
|
msgstr "Englisch"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:153
|
#: bookwyrm/settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Deutsch"
|
msgstr "Deutsch"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:154
|
#: bookwyrm/settings.py:157
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Spanisch"
|
msgstr "Spanisch"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:155
|
#: bookwyrm/settings.py:158
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Französisch"
|
msgstr "Französisch"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:156
|
#: bookwyrm/settings.py:159
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "Vereinfachtes Chinesisch"
|
msgstr "Vereinfachtes Chinesisch"
|
||||||
|
|
||||||
|
@ -178,24 +178,30 @@ msgstr "Laden fehlgeschlagen"
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr "In OpenLibrary ansehen"
|
msgstr "In OpenLibrary ansehen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:102
|
#: bookwyrm/templates/book/book.html:85
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "View on OpenLibrary"
|
||||||
|
msgid "View on Inventaire"
|
||||||
|
msgstr "In OpenLibrary ansehen"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/book.html:105
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(review_count)s review)"
|
msgid "(%(review_count)s review)"
|
||||||
msgid_plural "(%(review_count)s reviews)"
|
msgid_plural "(%(review_count)s reviews)"
|
||||||
msgstr[0] "(%(review_count)s Bewertung)"
|
msgstr[0] "(%(review_count)s Bewertung)"
|
||||||
msgstr[1] "(%(review_count)s Bewertungen)"
|
msgstr[1] "(%(review_count)s Bewertungen)"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:114
|
#: bookwyrm/templates/book/book.html:117
|
||||||
msgid "Add Description"
|
msgid "Add Description"
|
||||||
msgstr "Beschreibung hinzufügen"
|
msgstr "Beschreibung hinzufügen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:121
|
#: bookwyrm/templates/book/book.html:124
|
||||||
#: bookwyrm/templates/book/edit_book.html:107
|
#: bookwyrm/templates/book/edit_book.html:107
|
||||||
#: bookwyrm/templates/lists/form.html:12
|
#: bookwyrm/templates/lists/form.html:12
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr "Beschreibung:"
|
msgstr "Beschreibung:"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:125
|
#: bookwyrm/templates/book/book.html:128
|
||||||
#: bookwyrm/templates/book/edit_book.html:240
|
#: bookwyrm/templates/book/edit_book.html:240
|
||||||
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
||||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||||
|
@ -210,7 +216,7 @@ msgstr "Beschreibung:"
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Speichern"
|
msgstr "Speichern"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175
|
#: bookwyrm/templates/book/book.html:129 bookwyrm/templates/book/book.html:178
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit_book.html:241
|
#: bookwyrm/templates/book/edit_book.html:241
|
||||||
#: bookwyrm/templates/edit_author.html:79
|
#: bookwyrm/templates/edit_author.html:79
|
||||||
|
@ -226,19 +232,19 @@ msgstr "Speichern"
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Abbrechen"
|
msgstr "Abbrechen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:135
|
#: bookwyrm/templates/book/book.html:138
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid "<a href=\"%(path)s\">%(title)s</a> by "
|
#| msgid "<a href=\"%(path)s\">%(title)s</a> by "
|
||||||
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
||||||
msgstr "<a href=\"%(path)s\">%(title)s</a> von"
|
msgstr "<a href=\"%(path)s\">%(title)s</a> von"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:143
|
#: bookwyrm/templates/book/book.html:146
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
|
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
|
||||||
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
|
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:149
|
#: bookwyrm/templates/book/book.html:152
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid ""
|
#| msgid ""
|
||||||
#| " added <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list "
|
#| " added <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list "
|
||||||
|
@ -250,74 +256,74 @@ msgstr ""
|
||||||
"hat <em><a href=\"%(book_path)s\">%(book_title)s</a></em> zu deiner Liste "
|
"hat <em><a href=\"%(book_path)s\">%(book_title)s</a></em> zu deiner Liste "
|
||||||
"\"<a href=\"%(list_path)s\">%(list_name)s</a>\" Hinzugefügt"
|
"\"<a href=\"%(list_path)s\">%(list_name)s</a>\" Hinzugefügt"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:158
|
#: bookwyrm/templates/book/book.html:161
|
||||||
msgid "Your reading activity"
|
msgid "Your reading activity"
|
||||||
msgstr "Deine Leseaktivität"
|
msgstr "Deine Leseaktivität"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:160
|
#: bookwyrm/templates/book/book.html:163
|
||||||
msgid "Add read dates"
|
msgid "Add read dates"
|
||||||
msgstr "Lesedaten hinzufügen"
|
msgstr "Lesedaten hinzufügen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:165
|
#: bookwyrm/templates/book/book.html:168
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr "Du hast keine Leseaktivität für dieses Buch."
|
msgstr "Du hast keine Leseaktivität für dieses Buch."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:172
|
#: bookwyrm/templates/book/book.html:175
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr "Erstellen"
|
msgstr "Erstellen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:194
|
#: bookwyrm/templates/book/book.html:197
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr "Themen"
|
msgstr "Themen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:206
|
#: bookwyrm/templates/book/book.html:209
|
||||||
msgid "Places"
|
msgid "Places"
|
||||||
msgstr "Orte"
|
msgstr "Orte"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65
|
#: bookwyrm/templates/book/book.html:220 bookwyrm/templates/layout.html:65
|
||||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||||
#: bookwyrm/templates/search_results.html:91
|
#: bookwyrm/templates/search_results.html:115
|
||||||
#: bookwyrm/templates/user/user_layout.html:62
|
#: bookwyrm/templates/user/user_layout.html:62
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr "Listen"
|
msgstr "Listen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:228
|
#: bookwyrm/templates/book/book.html:231
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Go to list"
|
#| msgid "Go to list"
|
||||||
msgid "Add to list"
|
msgid "Add to list"
|
||||||
msgstr "Zur Liste"
|
msgstr "Zur Liste"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:238
|
#: bookwyrm/templates/book/book.html:241
|
||||||
#: bookwyrm/templates/book/cover_modal.html:31
|
#: bookwyrm/templates/book/cover_modal.html:31
|
||||||
#: bookwyrm/templates/lists/list.html:133
|
#: bookwyrm/templates/lists/list.html:133
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Hinzufügen"
|
msgstr "Hinzufügen"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:254
|
#: bookwyrm/templates/book/book.html:257
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Review"
|
#| msgid "Review"
|
||||||
msgid "Reviews"
|
msgid "Reviews"
|
||||||
msgstr "Bewerten"
|
msgstr "Bewerten"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:259
|
#: bookwyrm/templates/book/book.html:262
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your shelves"
|
#| msgid "Your shelves"
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr "Deine Regale"
|
msgstr "Deine Regale"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:265
|
#: bookwyrm/templates/book/book.html:268
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your Account"
|
#| msgid "Your Account"
|
||||||
msgid "Your comments"
|
msgid "Your comments"
|
||||||
msgstr "Dein Account"
|
msgstr "Dein Account"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:271
|
#: bookwyrm/templates/book/book.html:274
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your books"
|
#| msgid "Your books"
|
||||||
msgid "Your quotes"
|
msgid "Your quotes"
|
||||||
msgstr "Deine Bücher"
|
msgstr "Deine Bücher"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:305
|
#: bookwyrm/templates/book/book.html:308
|
||||||
msgid "rated it"
|
msgid "rated it"
|
||||||
msgstr "bewertet"
|
msgstr "bewertet"
|
||||||
|
|
||||||
|
@ -575,6 +581,7 @@ msgstr "Veröffentlicht von %(publisher)s."
|
||||||
#: bookwyrm/templates/feed/feed_layout.html:70
|
#: bookwyrm/templates/feed/feed_layout.html:70
|
||||||
#: bookwyrm/templates/get_started/layout.html:19
|
#: bookwyrm/templates/get_started/layout.html:19
|
||||||
#: bookwyrm/templates/get_started/layout.html:52
|
#: bookwyrm/templates/get_started/layout.html:52
|
||||||
|
#: bookwyrm/templates/search_results.html:72
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Schließen"
|
msgstr "Schließen"
|
||||||
|
|
||||||
|
@ -1123,7 +1130,7 @@ msgid "Search for a user"
|
||||||
msgstr "Suche nach Buch oder Benutzer*in"
|
msgstr "Suche nach Buch oder Benutzer*in"
|
||||||
|
|
||||||
#: bookwyrm/templates/get_started/users.html:13
|
#: bookwyrm/templates/get_started/users.html:13
|
||||||
#: bookwyrm/templates/search_results.html:76
|
#: bookwyrm/templates/search_results.html:99
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No users found for \"%(query)s\""
|
msgid "No users found for \"%(query)s\""
|
||||||
msgstr "Keine Nutzer*innen für \"%(query)s\" gefunden"
|
msgstr "Keine Nutzer*innen für \"%(query)s\" gefunden"
|
||||||
|
@ -1902,23 +1909,33 @@ msgstr "Profil"
|
||||||
msgid "Relationships"
|
msgid "Relationships"
|
||||||
msgstr "Beziehungen"
|
msgstr "Beziehungen"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:33
|
#: bookwyrm/templates/search_results.html:20
|
||||||
|
msgid "Log in to import or add books."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:38
|
||||||
msgid "Didn't find what you were looking for?"
|
msgid "Didn't find what you were looking for?"
|
||||||
msgstr "Nicht gefunden, wonach du gesucht hast?"
|
msgstr "Nicht gefunden, wonach du gesucht hast?"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:35
|
#: bookwyrm/templates/search_results.html:40
|
||||||
msgid "Show results from other catalogues"
|
msgid "Show results from other catalogues"
|
||||||
msgstr "Ergebnisse aus anderen Katalogen zeigen"
|
msgstr "Ergebnisse aus anderen Katalogen zeigen"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:62
|
#: bookwyrm/templates/search_results.html:44
|
||||||
msgid "Hide results from other catalogues"
|
msgid "Hide results from other catalogues"
|
||||||
msgstr "Ergebnisse aus anderen Katalogen ausblenden"
|
msgstr "Ergebnisse aus anderen Katalogen ausblenden"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:74
|
#: bookwyrm/templates/search_results.html:63
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Show more"
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Mehr anzeigen"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:97
|
||||||
msgid "Matching Users"
|
msgid "Matching Users"
|
||||||
msgstr "Passende Nutzer*innen"
|
msgstr "Passende Nutzer*innen"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:93
|
#: bookwyrm/templates/search_results.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No lists found for \"%(query)s\""
|
msgid "No lists found for \"%(query)s\""
|
||||||
msgstr "Keine Liste für \"%(query)s\" gefunden"
|
msgstr "Keine Liste für \"%(query)s\" gefunden"
|
||||||
|
@ -2728,12 +2745,7 @@ msgstr "kommentierte"
|
||||||
msgid "quoted"
|
msgid "quoted"
|
||||||
msgstr "zitierte"
|
msgstr "zitierte"
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:22
|
#: bookwyrm/templates/snippets/search_result_text.html:35
|
||||||
#, python-format
|
|
||||||
msgid "by %(author)s"
|
|
||||||
msgstr "von %(author)s"
|
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:30
|
|
||||||
msgid "Import book"
|
msgid "Import book"
|
||||||
msgstr "Buch importieren"
|
msgstr "Buch importieren"
|
||||||
|
|
||||||
|
@ -4495,6 +4507,10 @@ msgctxt "stick"
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid "by %(author)s"
|
||||||
|
#~ msgstr "von %(author)s"
|
||||||
|
|
||||||
#~ msgid "Deactivate user"
|
#~ msgid "Deactivate user"
|
||||||
#~ msgstr "Nutzer:in deaktivieren"
|
#~ msgstr "Nutzer:in deaktivieren"
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-26 09:56-0700\n"
|
"POT-Creation-Date: 2021-04-29 13:24-0700\n"
|
||||||
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: English <LL@li.org>\n"
|
"Language-Team: English <LL@li.org>\n"
|
||||||
|
@ -90,23 +90,23 @@ msgstr ""
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:152
|
#: bookwyrm/settings.py:155
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:153
|
#: bookwyrm/settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:154
|
#: bookwyrm/settings.py:157
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:155
|
#: bookwyrm/settings.py:158
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:156
|
#: bookwyrm/settings.py:159
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -166,24 +166,28 @@ msgstr ""
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:102
|
#: bookwyrm/templates/book/book.html:85
|
||||||
|
msgid "View on Inventaire"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/book.html:105
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(review_count)s review)"
|
msgid "(%(review_count)s review)"
|
||||||
msgid_plural "(%(review_count)s reviews)"
|
msgid_plural "(%(review_count)s reviews)"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:114
|
#: bookwyrm/templates/book/book.html:117
|
||||||
msgid "Add Description"
|
msgid "Add Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:121
|
#: bookwyrm/templates/book/book.html:124
|
||||||
#: bookwyrm/templates/book/edit_book.html:107
|
#: bookwyrm/templates/book/edit_book.html:107
|
||||||
#: bookwyrm/templates/lists/form.html:12
|
#: bookwyrm/templates/lists/form.html:12
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:125
|
#: bookwyrm/templates/book/book.html:128
|
||||||
#: bookwyrm/templates/book/edit_book.html:240
|
#: bookwyrm/templates/book/edit_book.html:240
|
||||||
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
||||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||||
|
@ -198,7 +202,7 @@ msgstr ""
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175
|
#: bookwyrm/templates/book/book.html:129 bookwyrm/templates/book/book.html:178
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit_book.html:241
|
#: bookwyrm/templates/book/edit_book.html:241
|
||||||
#: bookwyrm/templates/edit_author.html:79
|
#: bookwyrm/templates/edit_author.html:79
|
||||||
|
@ -214,81 +218,81 @@ msgstr ""
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:135
|
#: bookwyrm/templates/book/book.html:138
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:143
|
#: bookwyrm/templates/book/book.html:146
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:149
|
#: bookwyrm/templates/book/book.html:152
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
||||||
"href=\"%(shelf_path)s\">%(shelf_name)s</a> shelf."
|
"href=\"%(shelf_path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:158
|
#: bookwyrm/templates/book/book.html:161
|
||||||
msgid "Your reading activity"
|
msgid "Your reading activity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:160
|
#: bookwyrm/templates/book/book.html:163
|
||||||
msgid "Add read dates"
|
msgid "Add read dates"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:165
|
#: bookwyrm/templates/book/book.html:168
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:172
|
#: bookwyrm/templates/book/book.html:175
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:194
|
#: bookwyrm/templates/book/book.html:197
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:206
|
#: bookwyrm/templates/book/book.html:209
|
||||||
msgid "Places"
|
msgid "Places"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65
|
#: bookwyrm/templates/book/book.html:220 bookwyrm/templates/layout.html:65
|
||||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||||
#: bookwyrm/templates/search_results.html:91
|
#: bookwyrm/templates/search_results.html:115
|
||||||
#: bookwyrm/templates/user/user_layout.html:62
|
#: bookwyrm/templates/user/user_layout.html:62
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:228
|
#: bookwyrm/templates/book/book.html:231
|
||||||
msgid "Add to list"
|
msgid "Add to list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:238
|
#: bookwyrm/templates/book/book.html:241
|
||||||
#: bookwyrm/templates/book/cover_modal.html:31
|
#: bookwyrm/templates/book/cover_modal.html:31
|
||||||
#: bookwyrm/templates/lists/list.html:133
|
#: bookwyrm/templates/lists/list.html:133
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:254
|
#: bookwyrm/templates/book/book.html:257
|
||||||
msgid "Reviews"
|
msgid "Reviews"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:259
|
#: bookwyrm/templates/book/book.html:262
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:265
|
#: bookwyrm/templates/book/book.html:268
|
||||||
msgid "Your comments"
|
msgid "Your comments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:271
|
#: bookwyrm/templates/book/book.html:274
|
||||||
msgid "Your quotes"
|
msgid "Your quotes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:305
|
#: bookwyrm/templates/book/book.html:308
|
||||||
msgid "rated it"
|
msgid "rated it"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -531,6 +535,7 @@ msgstr ""
|
||||||
#: bookwyrm/templates/feed/feed_layout.html:70
|
#: bookwyrm/templates/feed/feed_layout.html:70
|
||||||
#: bookwyrm/templates/get_started/layout.html:19
|
#: bookwyrm/templates/get_started/layout.html:19
|
||||||
#: bookwyrm/templates/get_started/layout.html:52
|
#: bookwyrm/templates/get_started/layout.html:52
|
||||||
|
#: bookwyrm/templates/search_results.html:72
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1028,7 +1033,7 @@ msgid "Search for a user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/get_started/users.html:13
|
#: bookwyrm/templates/get_started/users.html:13
|
||||||
#: bookwyrm/templates/search_results.html:76
|
#: bookwyrm/templates/search_results.html:99
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No users found for \"%(query)s\""
|
msgid "No users found for \"%(query)s\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1735,23 +1740,31 @@ msgstr ""
|
||||||
msgid "Relationships"
|
msgid "Relationships"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:33
|
#: bookwyrm/templates/search_results.html:20
|
||||||
|
msgid "Log in to import or add books."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:38
|
||||||
msgid "Didn't find what you were looking for?"
|
msgid "Didn't find what you were looking for?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:35
|
#: bookwyrm/templates/search_results.html:40
|
||||||
msgid "Show results from other catalogues"
|
msgid "Show results from other catalogues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:62
|
#: bookwyrm/templates/search_results.html:44
|
||||||
msgid "Hide results from other catalogues"
|
msgid "Hide results from other catalogues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:74
|
#: bookwyrm/templates/search_results.html:63
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:97
|
||||||
msgid "Matching Users"
|
msgid "Matching Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:93
|
#: bookwyrm/templates/search_results.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No lists found for \"%(query)s\""
|
msgid "No lists found for \"%(query)s\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2481,12 +2494,7 @@ msgstr ""
|
||||||
msgid "quoted"
|
msgid "quoted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:22
|
#: bookwyrm/templates/snippets/search_result_text.html:35
|
||||||
#, python-format
|
|
||||||
msgid "by %(author)s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:30
|
|
||||||
msgid "Import book"
|
msgid "Import book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-26 09:56-0700\n"
|
"POT-Creation-Date: 2021-04-29 13:24-0700\n"
|
||||||
"PO-Revision-Date: 2021-03-19 11:49+0800\n"
|
"PO-Revision-Date: 2021-03-19 11:49+0800\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -90,23 +90,23 @@ msgstr "nombre de usuario"
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr "Ya existe un usuario con ese nombre."
|
msgstr "Ya existe un usuario con ese nombre."
|
||||||
|
|
||||||
#: bookwyrm/settings.py:152
|
#: bookwyrm/settings.py:155
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Inglés"
|
msgstr "Inglés"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:153
|
#: bookwyrm/settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Aléman"
|
msgstr "Aléman"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:154
|
#: bookwyrm/settings.py:157
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Español"
|
msgstr "Español"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:155
|
#: bookwyrm/settings.py:158
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Francés"
|
msgstr "Francés"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:156
|
#: bookwyrm/settings.py:159
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "Chino simplificado"
|
msgstr "Chino simplificado"
|
||||||
|
|
||||||
|
@ -166,24 +166,30 @@ msgstr "No se pudo cargar la portada"
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr "Ver en OpenLibrary"
|
msgstr "Ver en OpenLibrary"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:102
|
#: bookwyrm/templates/book/book.html:85
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "View on OpenLibrary"
|
||||||
|
msgid "View on Inventaire"
|
||||||
|
msgstr "Ver en OpenLibrary"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/book.html:105
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(review_count)s review)"
|
msgid "(%(review_count)s review)"
|
||||||
msgid_plural "(%(review_count)s reviews)"
|
msgid_plural "(%(review_count)s reviews)"
|
||||||
msgstr[0] "(%(review_count)s reseña)"
|
msgstr[0] "(%(review_count)s reseña)"
|
||||||
msgstr[1] "(%(review_count)s reseñas)"
|
msgstr[1] "(%(review_count)s reseñas)"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:114
|
#: bookwyrm/templates/book/book.html:117
|
||||||
msgid "Add Description"
|
msgid "Add Description"
|
||||||
msgstr "Agregar descripción"
|
msgstr "Agregar descripción"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:121
|
#: bookwyrm/templates/book/book.html:124
|
||||||
#: bookwyrm/templates/book/edit_book.html:107
|
#: bookwyrm/templates/book/edit_book.html:107
|
||||||
#: bookwyrm/templates/lists/form.html:12
|
#: bookwyrm/templates/lists/form.html:12
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr "Descripción:"
|
msgstr "Descripción:"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:125
|
#: bookwyrm/templates/book/book.html:128
|
||||||
#: bookwyrm/templates/book/edit_book.html:240
|
#: bookwyrm/templates/book/edit_book.html:240
|
||||||
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
||||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||||
|
@ -198,7 +204,7 @@ msgstr "Descripción:"
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Guardar"
|
msgstr "Guardar"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175
|
#: bookwyrm/templates/book/book.html:129 bookwyrm/templates/book/book.html:178
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit_book.html:241
|
#: bookwyrm/templates/book/edit_book.html:241
|
||||||
#: bookwyrm/templates/edit_author.html:79
|
#: bookwyrm/templates/edit_author.html:79
|
||||||
|
@ -214,18 +220,18 @@ msgstr "Guardar"
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Cancelar"
|
msgstr "Cancelar"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:135
|
#: bookwyrm/templates/book/book.html:138
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
||||||
msgstr "<a href=\"%(path)s/editions\">%(count)s ediciones</a>"
|
msgstr "<a href=\"%(path)s/editions\">%(count)s ediciones</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:143
|
#: bookwyrm/templates/book/book.html:146
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Esta edición está en tu <a href=\"%(path)s\">%(shelf_name)s</a> estante."
|
"Esta edición está en tu <a href=\"%(path)s\">%(shelf_name)s</a> estante."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:149
|
#: bookwyrm/templates/book/book.html:152
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
||||||
|
@ -234,72 +240,72 @@ msgstr ""
|
||||||
"Una <a href=\"%(book_path)s\">edición diferente</a> de este libro está en tu "
|
"Una <a href=\"%(book_path)s\">edición diferente</a> de este libro está en tu "
|
||||||
"<a href=\"%(shelf_path)s\">%(shelf_name)s</a> estante."
|
"<a href=\"%(shelf_path)s\">%(shelf_name)s</a> estante."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:158
|
#: bookwyrm/templates/book/book.html:161
|
||||||
msgid "Your reading activity"
|
msgid "Your reading activity"
|
||||||
msgstr "Tu actividad de lectura"
|
msgstr "Tu actividad de lectura"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:160
|
#: bookwyrm/templates/book/book.html:163
|
||||||
msgid "Add read dates"
|
msgid "Add read dates"
|
||||||
msgstr "Agregar fechas de lectura"
|
msgstr "Agregar fechas de lectura"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:165
|
#: bookwyrm/templates/book/book.html:168
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr "No tienes ninguna actividad de lectura para este libro."
|
msgstr "No tienes ninguna actividad de lectura para este libro."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:172
|
#: bookwyrm/templates/book/book.html:175
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr "Crear"
|
msgstr "Crear"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:194
|
#: bookwyrm/templates/book/book.html:197
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr "Sujetos"
|
msgstr "Sujetos"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:206
|
#: bookwyrm/templates/book/book.html:209
|
||||||
msgid "Places"
|
msgid "Places"
|
||||||
msgstr "Lugares"
|
msgstr "Lugares"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65
|
#: bookwyrm/templates/book/book.html:220 bookwyrm/templates/layout.html:65
|
||||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||||
#: bookwyrm/templates/search_results.html:91
|
#: bookwyrm/templates/search_results.html:115
|
||||||
#: bookwyrm/templates/user/user_layout.html:62
|
#: bookwyrm/templates/user/user_layout.html:62
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr "Listas"
|
msgstr "Listas"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:228
|
#: bookwyrm/templates/book/book.html:231
|
||||||
msgid "Add to list"
|
msgid "Add to list"
|
||||||
msgstr "Agregar a lista"
|
msgstr "Agregar a lista"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:238
|
#: bookwyrm/templates/book/book.html:241
|
||||||
#: bookwyrm/templates/book/cover_modal.html:31
|
#: bookwyrm/templates/book/cover_modal.html:31
|
||||||
#: bookwyrm/templates/lists/list.html:133
|
#: bookwyrm/templates/lists/list.html:133
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Agregar"
|
msgstr "Agregar"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:254
|
#: bookwyrm/templates/book/book.html:257
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Review"
|
#| msgid "Review"
|
||||||
msgid "Reviews"
|
msgid "Reviews"
|
||||||
msgstr "Reseña"
|
msgstr "Reseña"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:259
|
#: bookwyrm/templates/book/book.html:262
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your shelves"
|
#| msgid "Your shelves"
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr "Tus estantes"
|
msgstr "Tus estantes"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:265
|
#: bookwyrm/templates/book/book.html:268
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your Account"
|
#| msgid "Your Account"
|
||||||
msgid "Your comments"
|
msgid "Your comments"
|
||||||
msgstr "Tu cuenta"
|
msgstr "Tu cuenta"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:271
|
#: bookwyrm/templates/book/book.html:274
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your books"
|
#| msgid "Your books"
|
||||||
msgid "Your quotes"
|
msgid "Your quotes"
|
||||||
msgstr "Tus libros"
|
msgstr "Tus libros"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:305
|
#: bookwyrm/templates/book/book.html:308
|
||||||
msgid "rated it"
|
msgid "rated it"
|
||||||
msgstr "lo calificó con"
|
msgstr "lo calificó con"
|
||||||
|
|
||||||
|
@ -542,6 +548,7 @@ msgstr "Publicado por %(publisher)s."
|
||||||
#: bookwyrm/templates/feed/feed_layout.html:70
|
#: bookwyrm/templates/feed/feed_layout.html:70
|
||||||
#: bookwyrm/templates/get_started/layout.html:19
|
#: bookwyrm/templates/get_started/layout.html:19
|
||||||
#: bookwyrm/templates/get_started/layout.html:52
|
#: bookwyrm/templates/get_started/layout.html:52
|
||||||
|
#: bookwyrm/templates/search_results.html:72
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Cerrar"
|
msgstr "Cerrar"
|
||||||
|
|
||||||
|
@ -1054,7 +1061,7 @@ msgid "Search for a user"
|
||||||
msgstr "Buscar un usuario"
|
msgstr "Buscar un usuario"
|
||||||
|
|
||||||
#: bookwyrm/templates/get_started/users.html:13
|
#: bookwyrm/templates/get_started/users.html:13
|
||||||
#: bookwyrm/templates/search_results.html:76
|
#: bookwyrm/templates/search_results.html:99
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No users found for \"%(query)s\""
|
msgid "No users found for \"%(query)s\""
|
||||||
msgstr "No se encontró ningún usuario correspondiente a \"%(query)s\""
|
msgstr "No se encontró ningún usuario correspondiente a \"%(query)s\""
|
||||||
|
@ -1805,23 +1812,33 @@ msgstr "Perfil"
|
||||||
msgid "Relationships"
|
msgid "Relationships"
|
||||||
msgstr "Relaciones"
|
msgstr "Relaciones"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:33
|
#: bookwyrm/templates/search_results.html:20
|
||||||
|
msgid "Log in to import or add books."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:38
|
||||||
msgid "Didn't find what you were looking for?"
|
msgid "Didn't find what you were looking for?"
|
||||||
msgstr "¿No encontraste lo que buscabas?"
|
msgstr "¿No encontraste lo que buscabas?"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:35
|
#: bookwyrm/templates/search_results.html:40
|
||||||
msgid "Show results from other catalogues"
|
msgid "Show results from other catalogues"
|
||||||
msgstr "Mostrar resultados de otros catálogos"
|
msgstr "Mostrar resultados de otros catálogos"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:62
|
#: bookwyrm/templates/search_results.html:44
|
||||||
msgid "Hide results from other catalogues"
|
msgid "Hide results from other catalogues"
|
||||||
msgstr "Ocultar resultados de otros catálogos"
|
msgstr "Ocultar resultados de otros catálogos"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:74
|
#: bookwyrm/templates/search_results.html:63
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Show more"
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Mostrar más"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:97
|
||||||
msgid "Matching Users"
|
msgid "Matching Users"
|
||||||
msgstr "Usuarios correspondientes"
|
msgstr "Usuarios correspondientes"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:93
|
#: bookwyrm/templates/search_results.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No lists found for \"%(query)s\""
|
msgid "No lists found for \"%(query)s\""
|
||||||
msgstr "No se encontró ningúna lista correspondiente a \"%(query)s\""
|
msgstr "No se encontró ningúna lista correspondiente a \"%(query)s\""
|
||||||
|
@ -2571,12 +2588,7 @@ msgstr "comentó en"
|
||||||
msgid "quoted"
|
msgid "quoted"
|
||||||
msgstr "citó"
|
msgstr "citó"
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:22
|
#: bookwyrm/templates/snippets/search_result_text.html:35
|
||||||
#, python-format
|
|
||||||
msgid "by %(author)s"
|
|
||||||
msgstr "por %(author)s"
|
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:30
|
|
||||||
msgid "Import book"
|
msgid "Import book"
|
||||||
msgstr "Importar libro"
|
msgstr "Importar libro"
|
||||||
|
|
||||||
|
@ -4299,6 +4311,10 @@ msgctxt "stick"
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr "garrote"
|
msgstr "garrote"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid "by %(author)s"
|
||||||
|
#~ msgstr "por %(author)s"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
#~ msgid "%(rating)s star"
|
#~ msgid "%(rating)s star"
|
||||||
#~ msgid_plural "%(rating)s stars"
|
#~ msgid_plural "%(rating)s stars"
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.1.1\n"
|
"Project-Id-Version: 0.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-26 09:56-0700\n"
|
"POT-Creation-Date: 2021-04-29 13:24-0700\n"
|
||||||
"PO-Revision-Date: 2021-04-05 12:44+0100\n"
|
"PO-Revision-Date: 2021-04-05 12:44+0100\n"
|
||||||
"Last-Translator: Fabien Basmaison <contact@arkhi.org>\n"
|
"Last-Translator: Fabien Basmaison <contact@arkhi.org>\n"
|
||||||
"Language-Team: Mouse Reeve <LL@li.org>\n"
|
"Language-Team: Mouse Reeve <LL@li.org>\n"
|
||||||
|
@ -96,23 +96,23 @@ msgstr "nom du compte :"
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr "Ce nom est déjà associé à un compte."
|
msgstr "Ce nom est déjà associé à un compte."
|
||||||
|
|
||||||
#: bookwyrm/settings.py:152
|
#: bookwyrm/settings.py:155
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "English"
|
msgstr "English"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:153
|
#: bookwyrm/settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Deutsch"
|
msgstr "Deutsch"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:154
|
#: bookwyrm/settings.py:157
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Español"
|
msgstr "Español"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:155
|
#: bookwyrm/settings.py:158
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Français"
|
msgstr "Français"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:156
|
#: bookwyrm/settings.py:159
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "简化字"
|
msgstr "简化字"
|
||||||
|
|
||||||
|
@ -172,24 +172,30 @@ msgstr "La couverture n’a pu être chargée"
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr "Voir sur OpenLibrary"
|
msgstr "Voir sur OpenLibrary"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:102
|
#: bookwyrm/templates/book/book.html:85
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "View on OpenLibrary"
|
||||||
|
msgid "View on Inventaire"
|
||||||
|
msgstr "Voir sur OpenLibrary"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/book.html:105
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(review_count)s review)"
|
msgid "(%(review_count)s review)"
|
||||||
msgid_plural "(%(review_count)s reviews)"
|
msgid_plural "(%(review_count)s reviews)"
|
||||||
msgstr[0] "(%(review_count)s critique)"
|
msgstr[0] "(%(review_count)s critique)"
|
||||||
msgstr[1] "(%(review_count)s critiques)"
|
msgstr[1] "(%(review_count)s critiques)"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:114
|
#: bookwyrm/templates/book/book.html:117
|
||||||
msgid "Add Description"
|
msgid "Add Description"
|
||||||
msgstr "Ajouter une description"
|
msgstr "Ajouter une description"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:121
|
#: bookwyrm/templates/book/book.html:124
|
||||||
#: bookwyrm/templates/book/edit_book.html:107
|
#: bookwyrm/templates/book/edit_book.html:107
|
||||||
#: bookwyrm/templates/lists/form.html:12
|
#: bookwyrm/templates/lists/form.html:12
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr "Description :"
|
msgstr "Description :"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:125
|
#: bookwyrm/templates/book/book.html:128
|
||||||
#: bookwyrm/templates/book/edit_book.html:240
|
#: bookwyrm/templates/book/edit_book.html:240
|
||||||
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
||||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||||
|
@ -204,7 +210,7 @@ msgstr "Description :"
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Enregistrer"
|
msgstr "Enregistrer"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175
|
#: bookwyrm/templates/book/book.html:129 bookwyrm/templates/book/book.html:178
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit_book.html:241
|
#: bookwyrm/templates/book/edit_book.html:241
|
||||||
#: bookwyrm/templates/edit_author.html:79
|
#: bookwyrm/templates/edit_author.html:79
|
||||||
|
@ -220,18 +226,18 @@ msgstr "Enregistrer"
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Annuler"
|
msgstr "Annuler"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:135
|
#: bookwyrm/templates/book/book.html:138
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
||||||
msgstr "<a href=\"%(path)s/editions\">%(count)s éditions</a>"
|
msgstr "<a href=\"%(path)s/editions\">%(count)s éditions</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:143
|
#: bookwyrm/templates/book/book.html:146
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Cette édition est sur votre étagère <a href=\"%(path)s\">%(shelf_name)s</a>."
|
"Cette édition est sur votre étagère <a href=\"%(path)s\">%(shelf_name)s</a>."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:149
|
#: bookwyrm/templates/book/book.html:152
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
||||||
|
@ -240,72 +246,72 @@ msgstr ""
|
||||||
"Une <a href=\"%(book_path)s\">édition différente</a> de ce livre existe sur "
|
"Une <a href=\"%(book_path)s\">édition différente</a> de ce livre existe sur "
|
||||||
"votre étagère <a href=\"%(shelf_path)s\">%(shelf_name)s</a>."
|
"votre étagère <a href=\"%(shelf_path)s\">%(shelf_name)s</a>."
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:158
|
#: bookwyrm/templates/book/book.html:161
|
||||||
msgid "Your reading activity"
|
msgid "Your reading activity"
|
||||||
msgstr "Votre activité de lecture"
|
msgstr "Votre activité de lecture"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:160
|
#: bookwyrm/templates/book/book.html:163
|
||||||
msgid "Add read dates"
|
msgid "Add read dates"
|
||||||
msgstr "Ajouter des dates de lecture"
|
msgstr "Ajouter des dates de lecture"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:165
|
#: bookwyrm/templates/book/book.html:168
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr "Vous n’avez aucune activité de lecture pour ce livre"
|
msgstr "Vous n’avez aucune activité de lecture pour ce livre"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:172
|
#: bookwyrm/templates/book/book.html:175
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr "Créer"
|
msgstr "Créer"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:194
|
#: bookwyrm/templates/book/book.html:197
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr "Sujets"
|
msgstr "Sujets"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:206
|
#: bookwyrm/templates/book/book.html:209
|
||||||
msgid "Places"
|
msgid "Places"
|
||||||
msgstr "Lieux"
|
msgstr "Lieux"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65
|
#: bookwyrm/templates/book/book.html:220 bookwyrm/templates/layout.html:65
|
||||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||||
#: bookwyrm/templates/search_results.html:91
|
#: bookwyrm/templates/search_results.html:115
|
||||||
#: bookwyrm/templates/user/user_layout.html:62
|
#: bookwyrm/templates/user/user_layout.html:62
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr "Listes"
|
msgstr "Listes"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:228
|
#: bookwyrm/templates/book/book.html:231
|
||||||
msgid "Add to list"
|
msgid "Add to list"
|
||||||
msgstr "Ajouter à la liste"
|
msgstr "Ajouter à la liste"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:238
|
#: bookwyrm/templates/book/book.html:241
|
||||||
#: bookwyrm/templates/book/cover_modal.html:31
|
#: bookwyrm/templates/book/cover_modal.html:31
|
||||||
#: bookwyrm/templates/lists/list.html:133
|
#: bookwyrm/templates/lists/list.html:133
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Ajouter"
|
msgstr "Ajouter"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:254
|
#: bookwyrm/templates/book/book.html:257
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Review"
|
#| msgid "Review"
|
||||||
msgid "Reviews"
|
msgid "Reviews"
|
||||||
msgstr "Critique"
|
msgstr "Critique"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:259
|
#: bookwyrm/templates/book/book.html:262
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your shelves"
|
#| msgid "Your shelves"
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr "Vos étagères"
|
msgstr "Vos étagères"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:265
|
#: bookwyrm/templates/book/book.html:268
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your Account"
|
#| msgid "Your Account"
|
||||||
msgid "Your comments"
|
msgid "Your comments"
|
||||||
msgstr "Votre compte"
|
msgstr "Votre compte"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:271
|
#: bookwyrm/templates/book/book.html:274
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your books"
|
#| msgid "Your books"
|
||||||
msgid "Your quotes"
|
msgid "Your quotes"
|
||||||
msgstr "Vos livres"
|
msgstr "Vos livres"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:305
|
#: bookwyrm/templates/book/book.html:308
|
||||||
msgid "rated it"
|
msgid "rated it"
|
||||||
msgstr "l’a noté"
|
msgstr "l’a noté"
|
||||||
|
|
||||||
|
@ -548,6 +554,7 @@ msgstr "Publié par %(publisher)s."
|
||||||
#: bookwyrm/templates/feed/feed_layout.html:70
|
#: bookwyrm/templates/feed/feed_layout.html:70
|
||||||
#: bookwyrm/templates/get_started/layout.html:19
|
#: bookwyrm/templates/get_started/layout.html:19
|
||||||
#: bookwyrm/templates/get_started/layout.html:52
|
#: bookwyrm/templates/get_started/layout.html:52
|
||||||
|
#: bookwyrm/templates/search_results.html:72
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Fermer"
|
msgstr "Fermer"
|
||||||
|
|
||||||
|
@ -1066,7 +1073,7 @@ msgid "Search for a user"
|
||||||
msgstr "Chercher un compte"
|
msgstr "Chercher un compte"
|
||||||
|
|
||||||
#: bookwyrm/templates/get_started/users.html:13
|
#: bookwyrm/templates/get_started/users.html:13
|
||||||
#: bookwyrm/templates/search_results.html:76
|
#: bookwyrm/templates/search_results.html:99
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No users found for \"%(query)s\""
|
msgid "No users found for \"%(query)s\""
|
||||||
msgstr "Aucun compte trouvé pour « %(query)s »"
|
msgstr "Aucun compte trouvé pour « %(query)s »"
|
||||||
|
@ -1830,23 +1837,33 @@ msgstr "Profil"
|
||||||
msgid "Relationships"
|
msgid "Relationships"
|
||||||
msgstr "Relations"
|
msgstr "Relations"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:33
|
#: bookwyrm/templates/search_results.html:20
|
||||||
|
msgid "Log in to import or add books."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:38
|
||||||
msgid "Didn't find what you were looking for?"
|
msgid "Didn't find what you were looking for?"
|
||||||
msgstr "Vous n’avez pas trouvé ce que vous cherchiez ?"
|
msgstr "Vous n’avez pas trouvé ce que vous cherchiez ?"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:35
|
#: bookwyrm/templates/search_results.html:40
|
||||||
msgid "Show results from other catalogues"
|
msgid "Show results from other catalogues"
|
||||||
msgstr "Montrer les résultats d’autres catalogues"
|
msgstr "Montrer les résultats d’autres catalogues"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:62
|
#: bookwyrm/templates/search_results.html:44
|
||||||
msgid "Hide results from other catalogues"
|
msgid "Hide results from other catalogues"
|
||||||
msgstr "Masquer les résultats d’autres catalogues"
|
msgstr "Masquer les résultats d’autres catalogues"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:74
|
#: bookwyrm/templates/search_results.html:63
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Show more"
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Déplier"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:97
|
||||||
msgid "Matching Users"
|
msgid "Matching Users"
|
||||||
msgstr "Comptes correspondants"
|
msgstr "Comptes correspondants"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:93
|
#: bookwyrm/templates/search_results.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No lists found for \"%(query)s\""
|
msgid "No lists found for \"%(query)s\""
|
||||||
msgstr "Aucune liste trouvée pour « %(query)s »"
|
msgstr "Aucune liste trouvée pour « %(query)s »"
|
||||||
|
@ -2605,12 +2622,7 @@ msgstr "a commenté"
|
||||||
msgid "quoted"
|
msgid "quoted"
|
||||||
msgstr "a cité"
|
msgstr "a cité"
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:22
|
#: bookwyrm/templates/snippets/search_result_text.html:35
|
||||||
#, python-format
|
|
||||||
msgid "by %(author)s"
|
|
||||||
msgstr "par %(author)s"
|
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:30
|
|
||||||
msgid "Import book"
|
msgid "Import book"
|
||||||
msgstr "Importer le livre"
|
msgstr "Importer le livre"
|
||||||
|
|
||||||
|
@ -4341,6 +4353,10 @@ msgctxt "stick"
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid "by %(author)s"
|
||||||
|
#~ msgstr "par %(author)s"
|
||||||
|
|
||||||
#~ msgid "Deactivate user"
|
#~ msgid "Deactivate user"
|
||||||
#~ msgstr "Désactiver le compte"
|
#~ msgstr "Désactiver le compte"
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.1.1\n"
|
"Project-Id-Version: 0.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-26 09:56-0700\n"
|
"POT-Creation-Date: 2021-04-29 13:24-0700\n"
|
||||||
"PO-Revision-Date: 2021-03-20 00:56+0000\n"
|
"PO-Revision-Date: 2021-03-20 00:56+0000\n"
|
||||||
"Last-Translator: Kana <gudzpoz@live.com>\n"
|
"Last-Translator: Kana <gudzpoz@live.com>\n"
|
||||||
"Language-Team: Mouse Reeve <LL@li.org>\n"
|
"Language-Team: Mouse Reeve <LL@li.org>\n"
|
||||||
|
@ -96,23 +96,23 @@ msgstr "用户名"
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr "已经存在使用该用户名的用户。"
|
msgstr "已经存在使用该用户名的用户。"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:152
|
#: bookwyrm/settings.py:155
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "English(英语)"
|
msgstr "English(英语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:153
|
#: bookwyrm/settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Deutsch(德语)"
|
msgstr "Deutsch(德语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:154
|
#: bookwyrm/settings.py:157
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Español(西班牙语)"
|
msgstr "Español(西班牙语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:155
|
#: bookwyrm/settings.py:158
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Français(法语)"
|
msgstr "Français(法语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:156
|
#: bookwyrm/settings.py:159
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "简体中文"
|
msgstr "简体中文"
|
||||||
|
|
||||||
|
@ -172,23 +172,29 @@ msgstr "加载封面失败"
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr "在 OpenLibrary 查看"
|
msgstr "在 OpenLibrary 查看"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:102
|
#: bookwyrm/templates/book/book.html:85
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "View on OpenLibrary"
|
||||||
|
msgid "View on Inventaire"
|
||||||
|
msgstr "在 OpenLibrary 查看"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/book.html:105
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(review_count)s review)"
|
msgid "(%(review_count)s review)"
|
||||||
msgid_plural "(%(review_count)s reviews)"
|
msgid_plural "(%(review_count)s reviews)"
|
||||||
msgstr[0] "(%(review_count)s 则书评)"
|
msgstr[0] "(%(review_count)s 则书评)"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:114
|
#: bookwyrm/templates/book/book.html:117
|
||||||
msgid "Add Description"
|
msgid "Add Description"
|
||||||
msgstr "添加描述"
|
msgstr "添加描述"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:121
|
#: bookwyrm/templates/book/book.html:124
|
||||||
#: bookwyrm/templates/book/edit_book.html:107
|
#: bookwyrm/templates/book/edit_book.html:107
|
||||||
#: bookwyrm/templates/lists/form.html:12
|
#: bookwyrm/templates/lists/form.html:12
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr "描述:"
|
msgstr "描述:"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:125
|
#: bookwyrm/templates/book/book.html:128
|
||||||
#: bookwyrm/templates/book/edit_book.html:240
|
#: bookwyrm/templates/book/edit_book.html:240
|
||||||
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
#: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42
|
||||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||||
|
@ -203,7 +209,7 @@ msgstr "描述:"
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "保存"
|
msgstr "保存"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175
|
#: bookwyrm/templates/book/book.html:129 bookwyrm/templates/book/book.html:178
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit_book.html:241
|
#: bookwyrm/templates/book/edit_book.html:241
|
||||||
#: bookwyrm/templates/edit_author.html:79
|
#: bookwyrm/templates/edit_author.html:79
|
||||||
|
@ -219,17 +225,17 @@ msgstr "保存"
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "取消"
|
msgstr "取消"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:135
|
#: bookwyrm/templates/book/book.html:138
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
msgid "<a href=\"%(path)s/editions\">%(count)s editions</a>"
|
||||||
msgstr "<a href=\"%(path)s/editions\">%(count)s 个版本</a>"
|
msgstr "<a href=\"%(path)s/editions\">%(count)s 个版本</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:143
|
#: bookwyrm/templates/book/book.html:146
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
msgid "This edition is on your <a href=\"%(path)s\">%(shelf_name)s</a> shelf."
|
||||||
msgstr "此版本在你的 <a href=\"%(path)s\">%(shelf_name)s</a> 书架上。"
|
msgstr "此版本在你的 <a href=\"%(path)s\">%(shelf_name)s</a> 书架上。"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:149
|
#: bookwyrm/templates/book/book.html:152
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
"A <a href=\"%(book_path)s\">different edition</a> of this book is on your <a "
|
||||||
|
@ -238,72 +244,72 @@ msgstr ""
|
||||||
"本书的 <a href=\"%(book_path)s\">另一个版本</a> 在你的 <a href="
|
"本书的 <a href=\"%(book_path)s\">另一个版本</a> 在你的 <a href="
|
||||||
"\"%(shelf_path)s\">%(shelf_name)s</a> 书架上。"
|
"\"%(shelf_path)s\">%(shelf_name)s</a> 书架上。"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:158
|
#: bookwyrm/templates/book/book.html:161
|
||||||
msgid "Your reading activity"
|
msgid "Your reading activity"
|
||||||
msgstr "你的阅读活动"
|
msgstr "你的阅读活动"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:160
|
#: bookwyrm/templates/book/book.html:163
|
||||||
msgid "Add read dates"
|
msgid "Add read dates"
|
||||||
msgstr "添加阅读日期"
|
msgstr "添加阅读日期"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:165
|
#: bookwyrm/templates/book/book.html:168
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr "你还没有任何这本书的阅读活动。"
|
msgstr "你还没有任何这本书的阅读活动。"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:172
|
#: bookwyrm/templates/book/book.html:175
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr "创建"
|
msgstr "创建"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:194
|
#: bookwyrm/templates/book/book.html:197
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr "主题"
|
msgstr "主题"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:206
|
#: bookwyrm/templates/book/book.html:209
|
||||||
msgid "Places"
|
msgid "Places"
|
||||||
msgstr "地点"
|
msgstr "地点"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65
|
#: bookwyrm/templates/book/book.html:220 bookwyrm/templates/layout.html:65
|
||||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||||
#: bookwyrm/templates/search_results.html:91
|
#: bookwyrm/templates/search_results.html:115
|
||||||
#: bookwyrm/templates/user/user_layout.html:62
|
#: bookwyrm/templates/user/user_layout.html:62
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr "列表"
|
msgstr "列表"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:228
|
#: bookwyrm/templates/book/book.html:231
|
||||||
msgid "Add to list"
|
msgid "Add to list"
|
||||||
msgstr "添加到列表"
|
msgstr "添加到列表"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:238
|
#: bookwyrm/templates/book/book.html:241
|
||||||
#: bookwyrm/templates/book/cover_modal.html:31
|
#: bookwyrm/templates/book/cover_modal.html:31
|
||||||
#: bookwyrm/templates/lists/list.html:133
|
#: bookwyrm/templates/lists/list.html:133
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "添加"
|
msgstr "添加"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:254
|
#: bookwyrm/templates/book/book.html:257
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Review"
|
#| msgid "Review"
|
||||||
msgid "Reviews"
|
msgid "Reviews"
|
||||||
msgstr "书评"
|
msgstr "书评"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:259
|
#: bookwyrm/templates/book/book.html:262
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your shelves"
|
#| msgid "Your shelves"
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr "你的书架"
|
msgstr "你的书架"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:265
|
#: bookwyrm/templates/book/book.html:268
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your Account"
|
#| msgid "Your Account"
|
||||||
msgid "Your comments"
|
msgid "Your comments"
|
||||||
msgstr "你的帐号"
|
msgstr "你的帐号"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:271
|
#: bookwyrm/templates/book/book.html:274
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Your books"
|
#| msgid "Your books"
|
||||||
msgid "Your quotes"
|
msgid "Your quotes"
|
||||||
msgstr "你的书目"
|
msgstr "你的书目"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:305
|
#: bookwyrm/templates/book/book.html:308
|
||||||
msgid "rated it"
|
msgid "rated it"
|
||||||
msgstr "评价了"
|
msgstr "评价了"
|
||||||
|
|
||||||
|
@ -546,6 +552,7 @@ msgstr "由 %(publisher)s 出版。"
|
||||||
#: bookwyrm/templates/feed/feed_layout.html:70
|
#: bookwyrm/templates/feed/feed_layout.html:70
|
||||||
#: bookwyrm/templates/get_started/layout.html:19
|
#: bookwyrm/templates/get_started/layout.html:19
|
||||||
#: bookwyrm/templates/get_started/layout.html:52
|
#: bookwyrm/templates/get_started/layout.html:52
|
||||||
|
#: bookwyrm/templates/search_results.html:72
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "关闭"
|
msgstr "关闭"
|
||||||
|
|
||||||
|
@ -1046,7 +1053,7 @@ msgid "Search for a user"
|
||||||
msgstr "搜索用户"
|
msgstr "搜索用户"
|
||||||
|
|
||||||
#: bookwyrm/templates/get_started/users.html:13
|
#: bookwyrm/templates/get_started/users.html:13
|
||||||
#: bookwyrm/templates/search_results.html:76
|
#: bookwyrm/templates/search_results.html:99
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No users found for \"%(query)s\""
|
msgid "No users found for \"%(query)s\""
|
||||||
msgstr "没有找到 \"%(query)s\" 的用户"
|
msgstr "没有找到 \"%(query)s\" 的用户"
|
||||||
|
@ -1795,23 +1802,33 @@ msgstr "个人资料"
|
||||||
msgid "Relationships"
|
msgid "Relationships"
|
||||||
msgstr "关系"
|
msgstr "关系"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:33
|
#: bookwyrm/templates/search_results.html:20
|
||||||
|
msgid "Log in to import or add books."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:38
|
||||||
msgid "Didn't find what you were looking for?"
|
msgid "Didn't find what you were looking for?"
|
||||||
msgstr "没有找到你想找的?"
|
msgstr "没有找到你想找的?"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:35
|
#: bookwyrm/templates/search_results.html:40
|
||||||
msgid "Show results from other catalogues"
|
msgid "Show results from other catalogues"
|
||||||
msgstr "显示其它类别的结果"
|
msgstr "显示其它类别的结果"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:62
|
#: bookwyrm/templates/search_results.html:44
|
||||||
msgid "Hide results from other catalogues"
|
msgid "Hide results from other catalogues"
|
||||||
msgstr "隐藏其它类别的结果"
|
msgstr "隐藏其它类别的结果"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:74
|
#: bookwyrm/templates/search_results.html:63
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Show more"
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "显示更多"
|
||||||
|
|
||||||
|
#: bookwyrm/templates/search_results.html:97
|
||||||
msgid "Matching Users"
|
msgid "Matching Users"
|
||||||
msgstr "匹配的用户"
|
msgstr "匹配的用户"
|
||||||
|
|
||||||
#: bookwyrm/templates/search_results.html:93
|
#: bookwyrm/templates/search_results.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "No lists found for \"%(query)s\""
|
msgid "No lists found for \"%(query)s\""
|
||||||
msgstr "没有找到 \"%(query)s\" 的列表"
|
msgstr "没有找到 \"%(query)s\" 的列表"
|
||||||
|
@ -2570,12 +2587,7 @@ msgstr "评论了"
|
||||||
msgid "quoted"
|
msgid "quoted"
|
||||||
msgstr "引用了"
|
msgstr "引用了"
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:22
|
#: bookwyrm/templates/snippets/search_result_text.html:35
|
||||||
#, python-format
|
|
||||||
msgid "by %(author)s"
|
|
||||||
msgstr "由 %(author)s 所著"
|
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/search_result_text.html:30
|
|
||||||
msgid "Import book"
|
msgid "Import book"
|
||||||
msgstr "导入书目"
|
msgstr "导入书目"
|
||||||
|
|
||||||
|
@ -4292,6 +4304,10 @@ msgctxt "stick"
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid "by %(author)s"
|
||||||
|
#~ msgstr "由 %(author)s 所著"
|
||||||
|
|
||||||
#~ msgid "Deactivate user"
|
#~ msgid "Deactivate user"
|
||||||
#~ msgstr "停用用户"
|
#~ msgstr "停用用户"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
celery==4.4.2
|
celery==4.4.2
|
||||||
Django==3.1.8
|
Django==3.2.0
|
||||||
django-model-utils==4.0.0
|
django-model-utils==4.0.0
|
||||||
environs==7.2.0
|
environs==7.2.0
|
||||||
flower==0.9.4
|
flower==0.9.4
|
||||||
|
|
Loading…
Reference in a new issue