Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2021-03-07 09:00:20 -08:00
commit c770b369d2
61 changed files with 2609 additions and 302 deletions

View file

@ -31,7 +31,7 @@ Code contributions are gladly welcomed! If you're not sure where to start, take
If you have questions about the project or contributing, you can set up a video call during BookWyrm ["office hours"](https://calendly.com/mouse-reeve/30min). If you have questions about the project or contributing, you can set up a video call during BookWyrm ["office hours"](https://calendly.com/mouse-reeve/30min).
### Translation ### Translation
Do you speak a language besides English? BookWyrm needs localization! If you're comfortable using git and want to get into the code, there are [instructions](#workin-with-translations-and-locale-files) on how to create and edit localization files. If you feel more comfortable working in a regular text editor and would prefer not to run the application, get in touch directly and we can figure out a system, like emailing a text file, that works best. Do you speak a language besides English? BookWyrm needs localization! If you're comfortable using git and want to get into the code, there are [instructions](#working-with-translations-and-locale-files) on how to create and edit localization files. If you feel more comfortable working in a regular text editor and would prefer not to run the application, get in touch directly and we can figure out a system, like emailing a text file, that works best.
### Financial Support ### Financial Support
BookWyrm is an ad-free passion project with no intentions of seeking out venture funding or corporate financial relationships. If you want to help keep the project going, you can donate to the [Patreon](https://www.patreon.com/bookwyrm), or make a one time gift via [PayPal](https://paypal.me/oulipo). BookWyrm is an ad-free passion project with no intentions of seeking out venture funding or corporate financial relationships. If you want to help keep the project going, you can donate to the [Patreon](https://www.patreon.com/bookwyrm), or make a one time gift via [PayPal](https://paypal.me/oulipo).
@ -118,7 +118,7 @@ If you edit the CSS or JavaScript, you will need to run Django's `collectstatic`
./bw-dev collectstatic ./bw-dev collectstatic
``` ```
### Workin with translations and locale files ### Working with translations and locale files
Text in the html files are wrapped in translation tags (`{% trans %}` and `{% blocktrans %}`), and Django generates locale files for all the strings in which you can add translations for the text. You can find existing translations in the `locale/` directory. Text in the html files are wrapped in translation tags (`{% trans %}` and `{% blocktrans %}`), and Django generates locale files for all the strings in which you can add translations for the text. You can find existing translations in the `locale/` directory.
The application's language is set by a request header sent by your browser to the application, so to change the language of the application, you can change the default language requested by your browser. The application's language is set by a request header sent by your browser to the application, so to change the language of the application, you can change the default language requested by your browser.
@ -132,7 +132,10 @@ To start translation into a language which is currently supported, run the djang
#### Editing a locale #### Editing a locale
When you have a locale file, open the `django.po` in the directory for the language (for example, if you were adding German, `locale/de/LC_MESSAGES/django.po`. All the the text in the application will be shown in paired strings, with `msgid` as the original text, and `msgstr` as the translation (by default, this is set to an empty string, and will display the original text). When you have a locale file, open the `django.po` in the directory for the language (for example, if you were adding German, `locale/de/LC_MESSAGES/django.po`. All the the text in the application will be shown in paired strings, with `msgid` as the original text, and `msgstr` as the translation (by default, this is set to an empty string, and will display the original text).
Add you translations to the `msgstr` strings, and when you're ready, compile the locale by running: Add your translations to the `msgstr` strings. As the messages in the application are updated, `gettext` will sometimes add best-guess fuzzy matched options for those translations. When a message is marked as fuzzy, it will not be used in the application, so be sure to remove it when you translate that line.
When you're done, compile the locale by running:
``` bash ``` bash
./bw-dev compilemessages ./bw-dev compilemessages
``` ```

View file

@ -26,7 +26,7 @@ class Book(ActivityObject):
librarythingKey: str = '' librarythingKey: str = ''
goodreadsKey: str = '' goodreadsKey: str = ''
cover: Image = field(default_factory=lambda: {}) cover: Image = None
type: str = 'Book' type: str = 'Book'

View file

@ -26,6 +26,7 @@ class AbstractMinimalConnector(ABC):
'books_url', 'books_url',
'covers_url', 'covers_url',
'search_url', 'search_url',
'isbn_search_url',
'max_query_count', 'max_query_count',
'name', 'name',
'identifier', 'identifier',
@ -61,6 +62,30 @@ class AbstractMinimalConnector(ABC):
results.append(self.format_search_result(doc)) results.append(self.format_search_result(doc))
return results return results
def isbn_search(self, query):
''' isbn search '''
params = {}
resp = requests.get(
'%s%s' % (self.isbn_search_url, query),
params=params,
headers={
'Accept': 'application/json; charset=utf-8',
'User-Agent': settings.USER_AGENT,
},
)
if not resp.ok:
resp.raise_for_status()
try:
data = resp.json()
except ValueError as e:
logger.exception(e)
raise ConnectorException('Unable to parse json response', e)
results = []
for doc in self.parse_isbn_search_data(data):
results.append(self.format_isbn_search_result(doc))
return results
@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 '''
@ -73,6 +98,14 @@ class AbstractMinimalConnector(ABC):
def format_search_result(self, search_result): def format_search_result(self, search_result):
''' create a SearchResult obj from json ''' ''' create a SearchResult obj from json '''
@abstractmethod
def parse_isbn_search_data(self, data):
''' turn the result json from a search into a list '''
@abstractmethod
def format_isbn_search_result(self, search_result):
''' create a SearchResult obj from json '''
class AbstractConnector(AbstractMinimalConnector): class AbstractConnector(AbstractMinimalConnector):
''' generic book data connector ''' ''' generic book data connector '''

View file

@ -19,3 +19,11 @@ class Connector(AbstractMinimalConnector):
def format_search_result(self, search_result): def format_search_result(self, search_result):
search_result['connector'] = self search_result['connector'] = self
return SearchResult(**search_result) return SearchResult(**search_result)
def parse_isbn_search_data(self, data):
return data
def format_isbn_search_result(self, search_result):
search_result['connector'] = self
return SearchResult(**search_result)

View file

@ -1,5 +1,6 @@
''' interface with whatever connectors the app has ''' ''' interface with whatever connectors the app has '''
import importlib import importlib
import re
from urllib.parse import urlparse from urllib.parse import urlparse
from requests import HTTPError from requests import HTTPError
@ -15,13 +16,31 @@ class ConnectorException(HTTPError):
def search(query, min_confidence=0.1): def search(query, min_confidence=0.1):
''' find books based on arbitary keywords ''' ''' find books based on arbitary keywords '''
results = [] results = []
# Have we got a ISBN ?
isbn = re.sub('[\W_]', '', query)
maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13
dedup_slug = lambda r: '%s/%s/%s' % (r.title, r.author, r.year) dedup_slug = lambda r: '%s/%s/%s' % (r.title, r.author, r.year)
result_index = set() result_index = set()
for connector in get_connectors(): for connector in get_connectors():
try: result_set = None
result_set = connector.search(query, min_confidence=min_confidence) if maybe_isbn:
except (HTTPError, ConnectorException): # Search on ISBN
continue if not connector.isbn_search_url or connector.isbn_search_url == '':
result_set = []
else:
try:
result_set = connector.isbn_search(isbn)
except (HTTPError, ConnectorException):
pass
# if no isbn search or results, we fallback to generic search
if result_set == None or result_set == []:
try:
result_set = connector.search(query, min_confidence=min_confidence)
except (HTTPError, ConnectorException):
continue
result_set = [r for r in result_set \ result_set = [r for r in result_set \
if dedup_slug(r) not in result_index] if dedup_slug(r) not in result_index]
@ -41,6 +60,12 @@ def local_search(query, min_confidence=0.1, raw=False):
return connector.search(query, min_confidence=min_confidence, raw=raw) return connector.search(query, min_confidence=min_confidence, raw=raw)
def isbn_local_search(query, raw=False):
''' only look at local search results '''
connector = load_connector(models.Connector.objects.get(local=True))
return connector.isbn_search(query, raw=raw)
def first_search_result(query, min_confidence=0.1): def first_search_result(query, min_confidence=0.1):
''' search until you find a result that fits ''' ''' search until you find a result that fits '''
for connector in get_connectors(): for connector in get_connectors():

View file

@ -129,6 +129,22 @@ class Connector(AbstractConnector):
) )
def parse_isbn_search_data(self, data):
return list(data.values())
def format_isbn_search_result(self, search_result):
# build the remote id from the openlibrary key
key = self.books_url + search_result['key']
authors = search_result.get('authors') or [{'name': 'Unknown'}]
author_names = [ author.get('name') for author in authors]
return SearchResult(
title=search_result.get('title'),
key=key,
author=', '.join(author_names),
connector=self,
year=search_result.get('publish_date'),
)
def load_edition_data(self, olkey): def load_edition_data(self, olkey):
''' query openlibrary for editions of a work ''' ''' query openlibrary for editions of a work '''
url = '%s/works/%s/editions' % (self.books_url, olkey) url = '%s/works/%s/editions' % (self.books_url, olkey)

View file

@ -33,6 +33,31 @@ class Connector(AbstractConnector):
search_results.sort(key=lambda r: r.confidence, reverse=True) search_results.sort(key=lambda r: r.confidence, reverse=True)
return search_results return search_results
def isbn_search(self, query, raw=False):
''' search your local database '''
if not query:
return []
filters = [{f: query} for f in ['isbn_10', 'isbn_13']]
results = models.Edition.objects.filter(
reduce(operator.or_, (Q(**f) for f in filters))
).distinct()
# when there are multiple editions of the same work, pick the default.
# it would be odd for this to happen.
results = results.filter(parent_work__default_edition__id=F('id')) \
or results
search_results = []
for result in results:
if raw:
search_results.append(result)
else:
search_results.append(self.format_search_result(result))
if len(search_results) >= 10:
break
return search_results
def format_search_result(self, search_result): def format_search_result(self, search_result):
return SearchResult( return SearchResult(
@ -47,6 +72,19 @@ class Connector(AbstractConnector):
) )
def format_isbn_search_result(self, search_result):
return SearchResult(
title=search_result.title,
key=search_result.remote_id,
author=search_result.author_text,
year=search_result.published_date.year if \
search_result.published_date else None,
connector=self,
confidence=search_result.rank if \
hasattr(search_result, 'rank') else 1,
)
def is_work_data(self, data): def is_work_data(self, data):
pass pass
@ -59,6 +97,10 @@ class Connector(AbstractConnector):
def get_authors_from_data(self, data): def get_authors_from_data(self, data):
return None return None
def parse_isbn_search_data(self, data):
''' it's already in the right format, don't even worry about it '''
return data
def parse_search_data(self, data): def parse_search_data(self, data):
''' it's already in the right format, don't even worry about it ''' ''' it's already in the right format, don't even worry about it '''
return data return data

View file

@ -66,6 +66,7 @@ def init_connectors():
books_url='https://%s/book' % DOMAIN, books_url='https://%s/book' % DOMAIN,
covers_url='https://%s/images/covers' % DOMAIN, covers_url='https://%s/images/covers' % DOMAIN,
search_url='https://%s/search?q=' % DOMAIN, search_url='https://%s/search?q=' % DOMAIN,
isbn_search_url='https://%s/isbn/' % DOMAIN,
priority=1, priority=1,
) )
@ -77,6 +78,7 @@ def init_connectors():
books_url='https://bookwyrm.social/book', books_url='https://bookwyrm.social/book',
covers_url='https://bookwyrm.social/images/covers', covers_url='https://bookwyrm.social/images/covers',
search_url='https://bookwyrm.social/search?q=', search_url='https://bookwyrm.social/search?q=',
isbn_search_url='https://bookwyrm.social/isbn/',
priority=2, priority=2,
) )
@ -88,6 +90,7 @@ def init_connectors():
books_url='https://openlibrary.org', books_url='https://openlibrary.org',
covers_url='https://covers.openlibrary.org', covers_url='https://covers.openlibrary.org',
search_url='https://openlibrary.org/search?q=', search_url='https://openlibrary.org/search?q=',
isbn_search_url='https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:',
priority=3, priority=3,
) )

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2021-02-28 16:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bookwyrm', '0046_sitesettings_privacy_policy'),
]
operations = [
migrations.AddField(
model_name='connector',
name='isbn_search_url',
field=models.CharField(blank=True, max_length=255, null=True),
),
]

View file

@ -91,7 +91,7 @@ class Book(BookDataModel):
@property @property
def alt_text(self): def alt_text(self):
''' image alt test ''' ''' image alt test '''
text = '%s cover' % self.title text = '%s' % self.title
if self.edition_info: if self.edition_info:
text += ' (%s)' % self.edition_info text += ' (%s)' % self.edition_info
return text return text

View file

@ -22,6 +22,7 @@ class Connector(BookWyrmModel):
books_url = models.CharField(max_length=255) books_url = models.CharField(max_length=255)
covers_url = models.CharField(max_length=255) covers_url = models.CharField(max_length=255)
search_url = models.CharField(max_length=255, null=True, blank=True) search_url = models.CharField(max_length=255, null=True, blank=True)
isbn_search_url = models.CharField(max_length=255, null=True, blank=True)
politeness_delay = models.IntegerField(null=True, blank=True) #seconds politeness_delay = models.IntegerField(null=True, blank=True) #seconds
max_query_count = models.IntegerField(null=True, blank=True) max_query_count = models.IntegerField(null=True, blank=True)

View file

@ -3,7 +3,7 @@ import re
from urllib.parse import urlparse from urllib.parse import urlparse
from django.apps import apps from django.apps import apps
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser, Group
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
@ -208,6 +208,13 @@ class User(OrderedCollectionPageMixin, AbstractUser):
# an id needs to be set before we can proceed with related models # an id needs to be set before we can proceed with related models
super().save(*args, **kwargs) super().save(*args, **kwargs)
# make users editors by default
try:
self.groups.add(Group.objects.get(name='editor'))
except Group.DoesNotExist:
# this should only happen in tests
pass
# create keys and shelves for new local users # create keys and shelves for new local users
self.key_pair = KeyPair.objects.create( self.key_pair = KeyPair.objects.create(
remote_id='%s/#main-key' % self.remote_id) remote_id='%s/#main-key' % self.remote_id)

View file

@ -141,6 +141,7 @@ LANGUAGE_CODE = 'en-us'
LANGUAGES = [ LANGUAGES = [
('en-us', _('English')), ('en-us', _('English')),
('de-de', _('German')), ('de-de', _('German')),
('es', _('Spanish')),
('fr-fr', _('French')), ('fr-fr', _('French')),
('zh-cn', _('Simplified Chinese')), ('zh-cn', _('Simplified Chinese')),
] ]

View file

@ -1,3 +1,8 @@
html {
scroll-behavior: smooth;
scroll-padding-top: 20%;
}
/* --- --- */ /* --- --- */
.image { .image {
overflow: hidden; overflow: hidden;

View file

@ -8,9 +8,12 @@ window.onload = function() {
Array.from(document.getElementsByClassName('interaction')) Array.from(document.getElementsByClassName('interaction'))
.forEach(t => t.onsubmit = interact); .forEach(t => t.onsubmit = interact);
// select all // Toggle all checkboxes.
Array.from(document.getElementsByClassName('select-all')) document
.forEach(t => t.onclick = selectAll); .querySelectorAll('[data-action="toggle-all"]')
.forEach(input => {
input.addEventListener('change', toggleAllCheckboxes);
});
// tab groups // tab groups
Array.from(document.getElementsByClassName('tab-group')) Array.from(document.getElementsByClassName('tab-group'))
@ -136,9 +139,20 @@ function interact(e) {
.forEach(t => addRemoveClass(t, 'hidden', t.className.indexOf('hidden') == -1)); .forEach(t => addRemoveClass(t, 'hidden', t.className.indexOf('hidden') == -1));
} }
function selectAll(e) { /**
e.target.parentElement.parentElement.querySelectorAll('[type="checkbox"]') * Toggle all descendant checkboxes of a target.
.forEach(t => t.checked=true); *
* Use `data-target="ID_OF_TARGET"` on the node being listened to.
*
* @param {Event} event - change Event
* @return {undefined}
*/
function toggleAllCheckboxes(event) {
const mainCheckbox = event.target;
document
.querySelectorAll(`#${mainCheckbox.dataset.target} [type="checkbox"]`)
.forEach(checkbox => {checkbox.checked = mainCheckbox.checked;});
} }
function toggleMenu(e) { function toggleMenu(e) {

View file

@ -35,7 +35,7 @@
</div> </div>
<div class="columns"> <div class="columns">
<div class="column is-narrow"> <div class="column is-one-fifth">
{% include 'snippets/book_cover.html' with book=book size=large %} {% 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 %}
{% include 'snippets/shelve_button/shelve_button.html' %} {% include 'snippets/shelve_button/shelve_button.html' %}
@ -93,7 +93,7 @@
</section> </section>
</div> </div>
<div class="column"> <div class="column is-three-fifths">
<div class="block"> <div class="block">
<h3 class="field is-grouped"> <h3 class="field is-grouped">
{% include 'snippets/stars.html' with rating=rating %} {% include 'snippets/stars.html' with rating=rating %}
@ -201,7 +201,7 @@
</div> </div>
</div> </div>
<div class="column is-narrow"> <div class="column is-one-fifth">
{% if book.subjects %} {% if book.subjects %}
<section class="content block"> <section class="content block">
<h2 class="title is-5">{% trans "Subjects" %}</h2> <h2 class="title is-5">{% trans "Subjects" %}</h2>
@ -217,7 +217,7 @@
<section class="content block"> <section class="content block">
<h2 class="title is-5">{% trans "Places" %}</h2> <h2 class="title is-5">{% trans "Places" %}</h2>
<ul> <ul>
{% for place in book.subject_placess %} {% for place in book.subject_places %}
<li>{{ place }}</li> <li>{{ place }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
@ -254,8 +254,8 @@
<div> <div>
{% include 'snippets/username.html' with user=rating.user %} {% include 'snippets/username.html' with user=rating.user %}
</div> </div>
<div class="field is-grouped mb-0"> <div class="is-flex">
<div>{% trans "rated it" %}</div> <p class="mr-1">{% trans "rated it" %}</p>
{% include 'snippets/stars.html' with rating=rating.rating %} {% include 'snippets/stars.html' with rating=rating.rating %}
</div> </div>
<div> <div>

View file

@ -5,7 +5,7 @@
{% block dropdown-trigger %}{% endblock %} {% block dropdown-trigger %}{% endblock %}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<ul class="dropdown-content" role="menu" id="menu-options-{{ book.id }}"> <ul class="dropdown-content" role="menu" id="menu-options-{{ uuid }}">
{% block dropdown-list %}{% endblock %} {% block dropdown-list %}{% endblock %}
</ul> </ul>
</div> </div>

View file

@ -1,8 +1,15 @@
<div class="modal hidden" id="{{ controls_text }}-{{ controls_uid }}"> <div
role="dialog"
class="modal hidden"
id="{{ controls_text }}-{{ controls_uid }}"
aria-labelledby="modal-card-title-{{ controls_text }}-{{ controls_uid }}"
aria-modal="true"
>
{# @todo Implement focus traps to prevent tabbing out of the modal. #}
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-card"> <div class="modal-card">
<header class="modal-card-head" tabindex="0" id="modal-title-{{ controls_text }}-{{ controls_uid }}"> <header class="modal-card-head" tabindex="0" id="modal-title-{{ controls_text }}-{{ controls_uid }}">
<h2 class="modal-card-title"> <h2 class="modal-card-title" id="modal-card-title-{{ controls_text }}-{{ controls_uid }}">
{% block modal-title %}{% endblock %} {% block modal-title %}{% endblock %}
</h2> </h2>
{% include 'snippets/toggle/toggle_button.html' with label="close" class="delete" nonbutton=True %} {% include 'snippets/toggle/toggle_button.html' with label="close" class="delete" nonbutton=True %}
@ -18,7 +25,6 @@
</footer> </footer>
{% block modal-form-close %}{% endblock %} {% block modal-form-close %}{% endblock %}
</div> </div>
<label class="modal-close is-large" for="{{ controls_text }}-{{ controls_uid }}" aria-label="close"></label>
{% include 'snippets/toggle/toggle_button.html' with label="close" class="modal-close is-large" nonbutton=True %} {% include 'snippets/toggle/toggle_button.html' with label="close" class="modal-close is-large" nonbutton=True %}
</div> </div>

View file

@ -54,11 +54,11 @@
<div class="tile is-child box has-background-white-bis"> <div class="tile is-child box has-background-white-bis">
<h2 class="title is-4">{% trans "Your Account" %}</h2> <h2 class="title is-4">{% trans "Your Account" %}</h2>
{% include 'user/user_preview.html' with user=request.user %} {% include 'user/user_preview.html' with user=request.user %}
{% if request.user.summary %}
<div class="box content"> <div class="box content">
{% if request.user.summary %}
{{ request.user.summary | to_markdown | safe }} {{ request.user.summary | to_markdown | safe }}
{% endif %}
</div> </div>
{% endif %}
</div> </div>
{% endif %} {% endif %}
</div> </div>

View file

@ -1,4 +1,5 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load i18n %}
{% if book %} {% if book %}
<div class="columns"> <div class="columns">
<div class="column is-narrow"> <div class="column is-narrow">
@ -8,7 +9,7 @@
<div class="column"> <div class="column">
<h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3> <h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
{% if book.authors %} {% if book.authors %}
<p class="subtitle is-5">by {% include 'snippets/authors.html' with book=book %}</p> <p class="subtitle is-5">{% trans "by" %} {% include 'snippets/authors.html' with book=book %}</p>
{% endif %} {% endif %}
{% if book|book_description %} {% if book|book_description %}
<blockquote class="content">{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}</blockquote> <blockquote class="content">{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}</blockquote>

View file

@ -1,11 +1,12 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load i18n %}
{% if book %} {% if book %}
<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 %}</a>
{% include 'snippets/stars.html' with rating=book|rating:request.user %} {% include 'snippets/stars.html' with rating=book|rating:request.user %}
<h3 class="title is-6"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3> <h3 class="title is-6"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
{% if book.authors %} {% if book.authors %}
<p class="subtitle is-6">by {% include 'snippets/authors.html' with book=book %}</p> <p class="subtitle is-6">{% trans "by" %} {% include 'snippets/authors.html' with book=book %}</p>
{% endif %} {% endif %}
{% endif %} {% endif %}

View file

@ -6,13 +6,13 @@
<h1 class="title">{% blocktrans %}{{ tab_title }} Timeline{% endblocktrans %}</h1> <h1 class="title">{% blocktrans %}{{ tab_title }} Timeline{% endblocktrans %}</h1>
<div class="tabs"> <div class="tabs">
<ul> <ul>
<li class="{% if tab == 'home' %}is-active{% endif %}"> <li class="{% if tab == 'home' %}is-active{% endif %}"{% if tab == 'home' %} aria-current="page"{% endif %}>
<a href="/#feed">{% trans "Home" %}</a> <a href="/#feed">{% trans "Home" %}</a>
</li> </li>
<li class="{% if tab == 'local' %}is-active{% endif %}"> <li class="{% if tab == 'local' %}is-active{% endif %}"{% if tab == 'local' %} aria-current="page"{% endif %}>
<a href="/local#feed">{% trans "Local" %}</a> <a href="/local#feed">{% trans "Local" %}</a>
</li> </li>
<li class="{% if tab == 'federated' %}is-active{% endif %}"> <li class="{% if tab == 'federated' %}is-active{% endif %}"{% if tab == 'federated' %} aria-current="page"{% endif %}>
<a href="/federated#feed">{% trans "Federated" %}</a> <a href="/federated#feed">{% trans "Federated" %}</a>
</li> </li>
</ul> </ul>

View file

@ -4,7 +4,7 @@
{% block panel %} {% block panel %}
<header class="block"> <header class="block">
<a href="/#feed" class="button" data-back> <a href="/#feed" class="button" data-back>
<span class="icon icon-arrow-left" aira-hidden="true"></span> <span class="icon icon-arrow-left" aria-hidden="true"></span>
<span>{% trans "Back" %}</span> <span>{% trans "Back" %}</span>
</a> </a>
</header> </header>

View file

@ -5,7 +5,7 @@
{% block title %}{% trans "Import Status" %}{% endblock %} {% block title %}{% trans "Import Status" %}{% endblock %}
{% block content %} {% block content %}{% spaceless %}
<div class="block"> <div class="block">
<h1 class="title">{% trans "Import Status" %}</h1> <h1 class="title">{% trans "Import Status" %}</h1>
@ -36,8 +36,19 @@
{% if not job.retry %} {% if not job.retry %}
<form name="retry" action="/import/{{ job.id }}" method="post"> <form name="retry" action="/import/{{ job.id }}" method="post">
{% csrf_token %} {% csrf_token %}
<ul>
<fieldset> {% with failed_count=failed_items|length %}
{% if failed_count > 10 %}
<p class="block">
<a href="#select-all-failed-imports">
{% blocktrans %}Jump to the bottom of the list to select the {{ failed_count }} items which failed to import.{% endblocktrans %}
</a>
</p>
{% endif %}
{% endwith %}
<fieldset id="failed-imports">
<ul>
{% for item in failed_items %} {% for item in failed_items %}
<li class="pb-1"> <li class="pb-1">
<input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}"> <input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}">
@ -51,15 +62,28 @@
</p> </p>
</li> </li>
{% endfor %} {% endfor %}
</fieldset> </ul>
</ul> </fieldset>
<div class="block pt-1 select-all">
<label class="label"> <fieldset class="mt-3">
<input type="checkbox" class="checkbox"> <a name="select-all-failed-imports"></a>
<label class="label is-inline">
<input
id="toggle-all-checkboxes-failed-imports"
class="checkbox"
type="checkbox"
data-action="toggle-all"
data-target="failed-imports"
/>
{% trans "Select all" %} {% trans "Select all" %}
</label> </label>
</div>
<button class="button" type="submit">{% trans "Retry items" %}</button> <button class="button is-block mt-3" type="submit">{% trans "Retry items" %}</button>
</fieldset>
<hr>
{% else %} {% else %}
<ul> <ul>
{% for item in failed_items %} {% for item in failed_items %}
@ -123,4 +147,4 @@
</table> </table>
</div> </div>
</div> </div>
{% endblock %} {% endspaceless %}{% endblock %}

View file

@ -0,0 +1,33 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Search Results" %}{% endblock %}
{% block content %}
{% with book_results|first as local_results %}
<div class="block">
<h1 class="title">{% blocktrans %}Search Results for "{{ query }}"{% endblocktrans %}</h1>
</div>
<div class="block columns">
<div class="column">
<h2 class="title">{% trans "Matching Books" %}</h2>
<section class="block">
{% if not results %}
<p>{% blocktrans %}No books found for "{{ query }}"{% endblocktrans %}</p>
{% else %}
<ul>
{% for result in results %}
<li class="pd-4">
<a href="{{ result.key }}">{% include 'snippets/search_result_text.html' with result=result link=True %}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</section>
<div class="column">
</div>
</div>
{% endwith %}
{% endblock %}

View file

@ -22,7 +22,7 @@
<meta name="twitter:image:alt" content="BookWyrm Logo"> <meta name="twitter:image:alt" content="BookWyrm Logo">
</head> </head>
<body> <body>
<nav class="navbar container" role="navigation" aria-label="main navigation"> <nav class="navbar container" aria-label="main navigation">
<div class="navbar-brand"> <div class="navbar-brand">
<a class="navbar-item" href="/"> <a class="navbar-item" href="/">
<img class="image logo" src="{% if site.logo_small %}/images/{{ site.logo_small }}{% else %}/static/images/logo-small.png{% endif %}" alt="Home page"> <img class="image logo" src="{% if site.logo_small %}/images/{{ site.logo_small }}{% else %}/static/images/logo-small.png{% endif %}" alt="Home page">
@ -67,12 +67,20 @@
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-item has-dropdown is-hoverable">
<div class="navbar-link pulldown-menu" role="button" aria-expanded="false" tabindex="0" aria-haspopup="true" aria-controls="navbar-dropdown"><p> <a
href="{{ user.local_path }}"
class="navbar-link pulldown-menu"
role="button"
aria-expanded="false"
tabindex="0"
aria-haspopup="true"
aria-controls="navbar-dropdown"
>
{% include 'snippets/avatar.html' with user=request.user %} {% include 'snippets/avatar.html' with user=request.user %}
{% include 'snippets/username.html' with user=request.user %} <span class="ml-2">{% include 'snippets/username.html' with user=request.user anchor=false %}</span>
</p></div> </a>
<ul class="navbar-dropdown" id="navbar-dropdown"> <ul class="navbar-dropdown" id="navbar-dropdown">
<li> <li>
<a href="/direct-messages" class="navbar-item"> <a href="/direct-messages" class="navbar-item">
@ -95,7 +103,7 @@
</a> </a>
</li> </li>
{% if perms.bookwyrm.create_invites or perms.bookwyrm.edit_instance_settings%} {% if perms.bookwyrm.create_invites or perms.bookwyrm.edit_instance_settings%}
<hr class="navbar-divider"> <li class="navbar-divider" role="presentation"></li>
{% endif %} {% endif %}
{% if perms.bookwyrm.create_invites %} {% if perms.bookwyrm.create_invites %}
<li> <li>
@ -111,7 +119,7 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
<hr class="navbar-divider"> <li class="navbar-divider" role="presentation"></li>
<li> <li>
<a href="/logout" class="navbar-item"> <a href="/logout" class="navbar-item">
{% trans 'Log out' %} {% trans 'Log out' %}
@ -141,12 +149,12 @@
<div class="columns is-variable is-1"> <div class="columns is-variable is-1">
<div class="column"> <div class="column">
<label class="is-sr-only" for="id_localname">{% trans "Username:" %}</label> <label class="is-sr-only" for="id_localname">{% trans "Username:" %}</label>
<input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname" placeholder="username"> <input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname" placeholder="{% trans 'username' %}">
</div> </div>
<div class="column"> <div class="column">
<label class="is-sr-only" for="id_password">{% trans "Username:" %}</label> <label class="is-sr-only" for="id_password">{% trans "Username:" %}</label>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="password"> <input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="{% trans 'password' %}">
<p class="help"><a href="/password-reset">Forgot your password?</a></p> <p class="help"><a href="/password-reset">{% trans "Forgot your password?" %}</a></p>
</div> </div>
<div class="column is-narrow"> <div class="column is-narrow">
<button class="button is-primary" type="submit">{% trans "Log in" %}</button> <button class="button is-primary" type="submit">{% trans "Log in" %}</button>
@ -157,7 +165,7 @@
{% if site.allow_registration and request.path != '' and request.path != '/' %} {% if site.allow_registration and request.path != '' and request.path != '/' %}
<div class="column is-narrow"> <div class="column is-narrow">
<a href="/" class="button is-link"> <a href="/" class="button is-link">
Join {% trans "Join" %}
</a> </a>
</div> </div>
{% endif %} {% endif %}
@ -191,7 +199,7 @@
{% if site.support_link %} {% if site.support_link %}
<div class="column"> <div class="column">
<span class="icon icon-heart"></span> <span class="icon icon-heart"></span>
Support {{ site.name }} on <a href="{{ site.support_link }}" target="_blank">{{ site.support_title }}</a> {% blocktrans %}Support {{ site.name }} on <a href="{{ site.support_link }}" target="_blank">{{ site.support_title }}</a>{% endblocktrans %}
</div> </div>
{% endif %} {% endif %}
<div class="column"> <div class="column">

View file

@ -6,6 +6,6 @@
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title">{% trans "Not Found" %}</h1> <h1 class="title">{% trans "Not Found" %}</h1>
<p>{% trans "The page your requested doesn't seem to exist!" %}</p> <p>{% trans "The page you requested doesn't seem to exist!" %}</p>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -87,11 +87,11 @@
</div> </div>
{% elif notification.notification_type == 'BOOST' %} {% elif notification.notification_type == 'BOOST' %}
{% if related_status.status_type == 'Review' %} {% if related_status.status_type == 'Review' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">review of <em>{{ book.title }}</em></a>{% endblocktrans %} {% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">review of <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Comment' %} {% elif related_status.status_type == 'Comment' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">comment on<em>{{ book.title }}</em></a>{% endblocktrans %} {% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">comment on<em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Quotation' %} {% elif related_status.status_type == 'Quotation' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">quote from <em>{{ book.title }}</em></a>{% endblocktrans %} {% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">quote from <em>{{ book_title }}</em></a>{% endblocktrans %}
{% else %} {% else %}
{% blocktrans with related_path=related_status.local_path %}boosted your <a href="{{ related_path }}">status</a>{% endblocktrans %} {% blocktrans with related_path=related_status.local_path %}boosted your <a href="{{ related_path }}">status</a>{% endblocktrans %}
{% endif %} {% endif %}
@ -114,7 +114,9 @@
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
{% if related_status.content %} {% if related_status.content %}
<a href="{{ related_status.local_path }}">{{ related_status.content | safe | truncatewords_html:10 }}</a> <a href="{{ related_status.local_path }}">
{{ related_status.content | safe | truncatewords_html:10 }}{% if related_status.mention_books %} <em>{{ related_status.mention_books.first.title }}</em>{% endif %}
</a>
{% elif related_status.quote %} {% elif related_status.quote %}
<a href="{{ related_status.local_path }}">{{ related_status.quote | safe | truncatewords_html:10 }}</a> <a href="{{ related_status.local_path }}">{{ related_status.quote | safe | truncatewords_html:10 }}</a>
{% elif related_status.rating %} {% elif related_status.rating %}

View file

@ -1,3 +1,3 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
<img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" alt="{{ user.alt_text }}"> <img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" {% if ariaHide %}aria-hidden="true"{% endif %} alt="{{ user.alt_text }}">

View file

@ -6,8 +6,7 @@
<div class="no-cover book-cover"> <div class="no-cover book-cover">
<img class="book-cover" src="/static/images/no_cover.jpg" alt="No cover"> <img class="book-cover" src="/static/images/no_cover.jpg" alt="No cover">
<div> <div>
<p>{{ book.title }}</p> <p>{{ book.alt_text }}</p>
<p>({{ book.edition_info }})</p>
</div> </div>
</div> </div>
{% endif %} {% endif %}

View file

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
<nav class="pagination" role="navigation" aria-label="pagination"> <nav class="pagination" aria-label="pagination">
{% if page.has_previous %} {% if page.has_previous %}
<p class="pagination-previous"> <p class="pagination-previous">
<a href="{{ path }}?page={{ page.previous_page_number }}{{ anchor }}"> <a href="{{ path }}?page={{ page.previous_page_number }}{{ anchor }}">

View file

@ -67,4 +67,4 @@
</div> </div>
</form> </form>
</div> </div>
{% include 'snippets/delete_readthrough_modal.html' with controls_text="delete-readthrough" controls_uid=readthrough.id %} {% include 'snippets/delete_readthrough_modal.html' with controls_text="delete-readthrough" controls_uid=readthrough.id no_body=True %}

View file

@ -18,7 +18,7 @@
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<hr class="navbar-divider"> <li class="navbar-divider" role="presentation"></li>
<li> <li>
<form class="dropdown-item pt-0 pb-0" name="shelve" action="/unshelve/" method="post"> <form class="dropdown-item pt-0 pb-0" name="shelve" action="/unshelve/" method="post">
{% csrf_token %} {% csrf_token %}

View file

@ -3,10 +3,12 @@
<div class="block"> <div class="block">
{% if status.status_type == 'Review' %} {% if status.status_type == 'Review' %}
<div> <div>
<h3 class="title is-5 has-subtitle"> {% if status.name %}
{% if status.name %}<span dir="auto">{{ status.name }}</span><br>{% endif %} <h3 class="title is-5 has-subtitle" dir="auto">
{{ status.name|escape }}
</h3> </h3>
<p class="subtitle">{% include 'snippets/stars.html' with rating=status.rating %}</p> {% endif %}
{% include 'snippets/stars.html' with rating=status.rating %}
</div> </div>
{% endif %} {% endif %}
@ -35,7 +37,7 @@
{% if status.content and status.status_type != 'GeneratedNote' and status.status_type != 'Announce' %} {% if status.content and status.status_type != 'GeneratedNote' and status.status_type != 'Announce' %}
{% include 'snippets/trimmed_text.html' with full=status.content|safe %} {% include 'snippets/trimmed_text.html' with full=status.content|safe %}
{% endif %} {% endif %}
{% if status.attachments %} {% if status.attachments.exists %}
<div class="block"> <div class="block">
<div class="columns"> <div class="columns">
{% for attachment in status.attachments.all %} {% for attachment in status.attachments.all %}

View file

@ -1,7 +1,9 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load i18n %} {% load i18n %}
{% include 'snippets/avatar.html' with user=status.user %} <a href="{{ status.user.local_path }}">
{% include 'snippets/avatar.html' with user=status.user ariaHide="true" %}
{% include 'snippets/username.html' with user=status.user %} {% include 'snippets/username.html' with user=status.user %}
</a>
{% if status.status_type == 'GeneratedNote' %} {% if status.status_type == 'GeneratedNote' %}
{{ status.content | safe }} {{ status.content | safe }}

View file

@ -8,19 +8,29 @@
{% with full|to_markdown|safe|truncatewords_html:60 as trimmed %} {% with full|to_markdown|safe|truncatewords_html:60 as trimmed %}
{% if trimmed != full %} {% if trimmed != full %}
<div id="hide-full-{{ uuid }}"> <div id="hide-full-{{ uuid }}">
<div class="content" id="trimmed-{{ uuid }}"><span dir="auto">{{ trimmed }}</span> <div class="content" id="trimmed-{{ uuid }}">
{% trans "Show more" as button_text %} <p dir="auto">{{ trimmed }}</p>
{% include 'snippets/toggle/open_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
<div>
{% trans "Show more" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
</div>
</div> </div>
</div> </div>
<div id="full-{{ uuid }}" class="hidden"> <div id="full-{{ uuid }}" class="hidden">
<div class="content"><span dir="auto">{{ full }}</span> <div class="content">
{% trans "Show less" as button_text %} <div dir="auto">{{ full }}</div>
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
<div>
{% trans "Show less" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
</div>
</div> </div>
</div> </div>
{% else %} {% else %}
<div class="content"><span dir="auto">{{ full }}</span></div> <div class="content">
<div dir="auto">{{ full }}</div>
</div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}

View file

@ -1,2 +1,13 @@
{% spaceless %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
<a href="{{ user.local_path }}" class="user">{% if user.name %}{{ user.name }}{% else %}{{ user | username }}{% endif %}</a>{% if possessive %}'s{% endif %}{% if show_full and user.name or show_full and user.localname %} ({{ user.username }}){% endif %}
<{% if anchor %}a href="{{ user.local_path }}"{% else %}span{% endif %}>
{{ user.display_name }}
</a>
{% if possessive %}'s{% endif %}
{% if show_full and user.name or show_full and user.localname %}
({{ user.username }})
{% endif %}
{% endspaceless %}

View file

@ -1,7 +1,7 @@
{% extends 'user/user_layout.html' %} {% extends 'user/user_layout.html' %}
{% load i18n %} {% load i18n %}
{% block title %}{{ user.name }}{% endblock %} {% block title %}{{ user.display_name }}{% endblock %}
{% block header %} {% block header %}
<div class="columns is-mobile"> <div class="columns is-mobile">
@ -67,7 +67,7 @@
</div> </div>
</div> </div>
{% for activity in activities %} {% for activity in activities %}
<div class="block" id="feed"> <div class="block" id="feed-{{ activity.id }}">
{% include 'snippets/status/status.html' with status=activity %} {% include 'snippets/status/status.html' with status=activity %}
</div> </div>
{% endfor %} {% endfor %}

View file

@ -17,11 +17,11 @@
{% include 'user/user_preview.html' with user=user %} {% include 'user/user_preview.html' with user=user %}
</div> </div>
{% if user.summary %}
<div class="column box has-background-white-bis content"> <div class="column box has-background-white-bis content">
{% if user.summary %}
{{ user.summary | to_markdown | safe }} {{ user.summary | to_markdown | safe }}
{% endif %}
</div> </div>
{% endif %}
</div> </div>
{% if not is_self and request.user.is_authenticated %} {% if not is_self and request.user.is_authenticated %}
{% include 'snippets/follow_button.html' with user=user %} {% include 'snippets/follow_button.html' with user=user %}
@ -56,7 +56,7 @@
<a href="{{ url }}">{% trans "Reading Goal" %}</a> <a href="{{ url }}">{% trans "Reading Goal" %}</a>
</li> </li>
{% endif %} {% endif %}
{% if is_self or user.lists.exists %} {% if is_self or user.list_set.exists %}
{% url 'user-lists' user|username as url %} {% url 'user-lists' user|username as url %}
<li{% if url in request.path %} class="is-active"{% endif %}> <li{% if url in request.path %} class="is-active"{% endif %}>
<a href="{{ url }}">{% trans "Lists" %}</a> <a href="{{ url }}">{% trans "Lists" %}</a>

View file

@ -1 +0,0 @@
from . import *

View file

@ -42,6 +42,10 @@ class AbstractConnector(TestCase):
return search_result return search_result
def parse_search_data(self, data): def parse_search_data(self, data):
return data return data
def format_isbn_search_result(self, search_result):
return search_result
def parse_isbn_search_data(self, data):
return data
def is_work_data(self, data): def is_work_data(self, data):
return data['type'] == 'work' return data['type'] == 'work'
def get_edition_from_work_data(self, data): def get_edition_from_work_data(self, data):

View file

@ -18,6 +18,7 @@ class AbstractConnector(TestCase):
books_url='https://example.com/books', books_url='https://example.com/books',
covers_url='https://example.com/covers', covers_url='https://example.com/covers',
search_url='https://example.com/search?q=', search_url='https://example.com/search?q=',
isbn_search_url='https://example.com/isbn',
) )
class TestConnector(abstract_connector.AbstractMinimalConnector): class TestConnector(abstract_connector.AbstractMinimalConnector):
@ -28,6 +29,10 @@ class AbstractConnector(TestCase):
pass pass
def parse_search_data(self, data): def parse_search_data(self, data):
return data return data
def format_isbn_search_result(self, search_result):
return search_result
def parse_isbn_search_data(self, data):
return data
self.test_connector = TestConnector('example.com') self.test_connector = TestConnector('example.com')
@ -39,6 +44,7 @@ class AbstractConnector(TestCase):
self.assertEqual(connector.books_url, 'https://example.com/books') self.assertEqual(connector.books_url, 'https://example.com/books')
self.assertEqual(connector.covers_url, 'https://example.com/covers') self.assertEqual(connector.covers_url, 'https://example.com/covers')
self.assertEqual(connector.search_url, 'https://example.com/search?q=') self.assertEqual(connector.search_url, 'https://example.com/search?q=')
self.assertEqual(connector.isbn_search_url, 'https://example.com/isbn')
self.assertIsNone(connector.name) self.assertIsNone(connector.name)
self.assertEqual(connector.identifier, 'example.com') self.assertEqual(connector.identifier, 'example.com')
self.assertIsNone(connector.max_query_count) self.assertIsNone(connector.max_query_count)

View file

@ -27,6 +27,7 @@ class Openlibrary(TestCase):
books_url='https://openlibrary.org', books_url='https://openlibrary.org',
covers_url='https://covers.openlibrary.org', covers_url='https://covers.openlibrary.org',
search_url='https://openlibrary.org/search?q=', search_url='https://openlibrary.org/search?q=',
isbn_search_url='https://openlibrary.org/isbn',
) )
self.connector = Connector('openlibrary.org') self.connector = Connector('openlibrary.org')
@ -149,6 +150,34 @@ class Openlibrary(TestCase):
self.assertEqual(result.connector, self.connector) self.assertEqual(result.connector, self.connector)
def test_parse_isbn_search_result(self):
''' extract the results from the search json response '''
datafile = pathlib.Path(__file__).parent.joinpath(
'../data/ol_isbn_search.json')
search_data = json.loads(datafile.read_bytes())
result = self.connector.parse_isbn_search_data(search_data)
self.assertIsInstance(result, list)
self.assertEqual(len(result), 1)
def test_format_isbn_search_result(self):
''' translate json from openlibrary into SearchResult '''
datafile = pathlib.Path(__file__).parent.joinpath(
'../data/ol_isbn_search.json')
search_data = json.loads(datafile.read_bytes())
results = self.connector.parse_isbn_search_data(search_data)
self.assertIsInstance(results, list)
result = self.connector.format_isbn_search_result(results[0])
self.assertIsInstance(result, SearchResult)
self.assertEqual(result.title, 'Les ombres errantes')
self.assertEqual(
result.key, 'https://openlibrary.org/books/OL16262504M')
self.assertEqual(result.author, 'Pascal Quignard')
self.assertEqual(result.year, '2002')
self.assertEqual(result.connector, self.connector)
@responses.activate @responses.activate
def test_load_edition_data(self): def test_load_edition_data(self):
''' format url from key and make request ''' ''' format url from key and make request '''

View file

@ -0,0 +1,45 @@
{
"ISBN:9782070427796": {
"url": "https://openlibrary.org/books/OL16262504M/Les_ombres_errantes",
"key": "/books/OL16262504M",
"title": "Les ombres errantes",
"authors": [
{
"url": "https://openlibrary.org/authors/OL269675A/Pascal_Quignard",
"name": "Pascal Quignard"
}
],
"by_statement": "Pascal Quignard.",
"identifiers": {
"goodreads": [
"1835483"
],
"librarything": [
"983474"
],
"isbn_10": [
"207042779X"
],
"openlibrary": [
"OL16262504M"
]
},
"classifications": {
"dewey_decimal_class": [
"848/.91403"
]
},
"publishers": [
{
"name": "Gallimard"
}
],
"publish_places": [
{
"name": "Paris"
}
],
"publish_date": "2002",
"notes": "Hardback published Grasset, 2002."
}
}

View file

@ -81,7 +81,7 @@ class Book(TestCase):
book.save() book.save()
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020') self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
self.assertEqual( self.assertEqual(
book.alt_text, 'Test Edition cover (worm, Glorbish language, 2020)') book.alt_text, 'Test Edition (worm, Glorbish language, 2020)')
def test_get_rank(self): def test_get_rank(self):

View file

@ -150,7 +150,7 @@ class Status(TestCase):
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url)) (settings.DOMAIN, self.book.cover.url))
self.assertEqual( self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover') activity['attachment'][0].name, 'Test Edition')
def test_comment_to_activity(self, _): def test_comment_to_activity(self, _):
''' subclass of the base model version with a "pure" serializer ''' ''' subclass of the base model version with a "pure" serializer '''
@ -177,7 +177,7 @@ class Status(TestCase):
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url)) (settings.DOMAIN, self.book.cover.url))
self.assertEqual( self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover') activity['attachment'][0].name, 'Test Edition')
def test_quotation_to_activity(self, _): def test_quotation_to_activity(self, _):
''' subclass of the base model version with a "pure" serializer ''' ''' subclass of the base model version with a "pure" serializer '''
@ -207,7 +207,7 @@ class Status(TestCase):
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url)) (settings.DOMAIN, self.book.cover.url))
self.assertEqual( self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover') activity['attachment'][0].name, 'Test Edition')
def test_review_to_activity(self, _): def test_review_to_activity(self, _):
''' subclass of the base model version with a "pure" serializer ''' ''' subclass of the base model version with a "pure" serializer '''
@ -238,7 +238,7 @@ class Status(TestCase):
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url)) (settings.DOMAIN, self.book.cover.url))
self.assertEqual( self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover') activity['attachment'][0].name, 'Test Edition')
def test_favorite(self, _): def test_favorite(self, _):
''' fav a status ''' ''' fav a status '''

View file

@ -0,0 +1,54 @@
''' test for app action functionality '''
import json
from unittest.mock import patch
from django.http import JsonResponse
from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm.connectors import abstract_connector
from bookwyrm.settings import DOMAIN
class IsbnViews(TestCase):
''' tag views'''
def setUp(self):
''' we need basic test data and mocks '''
self.factory = RequestFactory()
self.local_user = models.User.objects.create_user(
'mouse@local.com', 'mouse@mouse.com', 'mouseword',
local=True, localname='mouse',
remote_id='https://example.com/users/mouse',
)
self.work = models.Work.objects.create(title='Test Work')
self.book = models.Edition.objects.create(
title='Test Book',
isbn_13='1234567890123',
remote_id='https://example.com/book/1',
parent_work=self.work
)
models.Connector.objects.create(
identifier='self',
connector_file='self_connector',
local=True
)
models.SiteSettings.objects.create()
def test_isbn_json_response(self):
''' searches local data only and returns book data in json format '''
view = views.Isbn.as_view()
request = self.factory.get('')
with patch('bookwyrm.views.isbn.is_api_request') as is_api:
is_api.return_value = True
response = view(request, isbn='1234567890123')
self.assertIsInstance(response, JsonResponse)
data = json.loads(response.content)
self.assertEqual(len(data), 1)
self.assertEqual(data[0]['title'], 'Test Book')
self.assertEqual(
data[0]['key'], 'https://%s/book/%d' % (DOMAIN, self.book.id))

View file

@ -64,6 +64,10 @@ class ShelfViews(TestCase):
pass pass
def parse_search_data(self, data): def parse_search_data(self, data):
pass pass
def format_isbn_search_result(self, search_result):
return search_result
def parse_isbn_search_data(self, data):
return data
models.Connector.objects.create( models.Connector.objects.create(
identifier='example.com', identifier='example.com',
connector_file='openlibrary', connector_file='openlibrary',

View file

@ -135,6 +135,9 @@ urlpatterns = [
re_path(r'^resolve-book/?$', views.resolve_book), re_path(r'^resolve-book/?$', views.resolve_book),
re_path(r'^switch-edition/?$', views.switch_edition), re_path(r'^switch-edition/?$', views.switch_edition),
# isbn
re_path(r'^isbn/(?P<isbn>\d+)(.json)?/?$', views.Isbn.as_view()),
# author # author
re_path(r'^author/(?P<author_id>\d+)(.json)?/?$', views.Author.as_view()), re_path(r'^author/(?P<author_id>\d+)(.json)?/?$', views.Author.as_view()),
re_path(r'^author/(?P<author_id>\d+)/edit/?$', views.EditAuthor.as_view()), re_path(r'^author/(?P<author_id>\d+)/edit/?$', views.EditAuthor.as_view()),

View file

@ -31,3 +31,4 @@ from .site import Site
from .status import CreateStatus, DeleteStatus from .status import CreateStatus, DeleteStatus
from .updates import Updates from .updates import Updates
from .user import User, EditUser, Followers, Following from .user import User, EditUser, Followers, Following
from .isbn import Isbn

View file

@ -89,7 +89,7 @@ class Book(View):
'rating': reviews.aggregate(Avg('rating'))['rating__avg'], 'rating': reviews.aggregate(Avg('rating'))['rating__avg'],
'tags': models.UserTag.objects.filter(book=book), 'tags': models.UserTag.objects.filter(book=book),
'lists': privacy_filter( 'lists': privacy_filter(
request.user, book.list_set.all() request.user, book.list_set.filter(listitem__approved=True)
), ),
'user_tags': user_tags, 'user_tags': user_tags,
'user_shelves': user_shelves, 'user_shelves': user_shelves,

29
bookwyrm/views/isbn.py Normal file
View file

@ -0,0 +1,29 @@
''' isbn search view '''
from django.http import HttpResponseNotFound
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.http import require_POST
from bookwyrm import forms, models
from bookwyrm.connectors import connector_manager
from .helpers import is_api_request
# pylint: disable= no-self-use
class Isbn(View):
''' search a book by isbn '''
def get(self, request, isbn):
''' info about a book '''
book_results = connector_manager.isbn_local_search(isbn)
if is_api_request(request):
return JsonResponse([r.json() for r in book_results], safe=False)
data = {
'title': 'ISBN Search Results',
'results': book_results,
'query': isbn,
}
return TemplateResponse(request, 'isbn_search_results.html', data)

Binary file not shown.

View file

@ -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-03-02 21:36+0000\n" "POT-Creation-Date: 2021-03-04 22:24+0000\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"
@ -55,7 +55,7 @@ msgstr "%(value)s ist keine gültige remote_id"
msgid "%(value)s is not a valid username" msgid "%(value)s is not a valid username"
msgstr "%(value)s ist kein gültiger Username" msgstr "%(value)s ist kein gültiger Username"
#: bookwyrm/models/fields.py:164 #: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
#, fuzzy #, fuzzy
#| msgid "Server name" #| msgid "Server name"
msgid "username" msgid "username"
@ -74,10 +74,14 @@ msgid "German"
msgstr "Deutsch" msgstr "Deutsch"
#: bookwyrm/settings.py:144 #: bookwyrm/settings.py:144
msgid "Spanish"
msgstr ""
#: bookwyrm/settings.py:145
msgid "French" msgid "French"
msgstr "Französisch" msgstr "Französisch"
#: bookwyrm/settings.py:145 #: bookwyrm/settings.py:146
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "Vereinfachtes Chinesisch" msgstr "Vereinfachtes Chinesisch"
@ -96,6 +100,8 @@ msgid "Books by %(name)s"
msgstr "Bücher von %(name)s" msgstr "Bücher von %(name)s"
#: bookwyrm/templates/book.html:21 #: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by" msgid "by"
msgstr "von" msgstr "von"
@ -428,7 +434,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>" msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/feed/direct_messages.html:10 #: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79 #: bookwyrm/templates/layout.html:87
msgid "Direct Messages" msgid "Direct Messages"
msgstr "Direktnachrichten" msgstr "Direktnachrichten"
@ -538,7 +544,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "%(username)ss %(year)s Bücher" msgstr "%(username)ss %(year)s Bücher"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94 #: bookwyrm/templates/layout.html:102
msgid "Import Books" msgid "Import Books"
msgstr "Bücher importieren" msgstr "Bücher importieren"
@ -661,55 +667,72 @@ msgstr "Deine Regale"
msgid "Feed" msgid "Feed"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:84 #: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14 #: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile" msgid "Profile"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:89 #: bookwyrm/templates/layout.html:97
msgid "Settings" msgid "Settings"
msgstr "Einstellungen" msgstr "Einstellungen"
#: bookwyrm/templates/layout.html:103 #: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19 #: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3 #: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites" msgid "Invites"
msgstr "Einladungen" msgstr "Einladungen"
#: bookwyrm/templates/layout.html:110 #: bookwyrm/templates/layout.html:118
msgid "Site Configuration" msgid "Site Configuration"
msgstr "Seiteneinstellungen" msgstr "Seiteneinstellungen"
#: bookwyrm/templates/layout.html:117 #: bookwyrm/templates/layout.html:125
msgid "Log out" msgid "Log out"
msgstr "Abmelden" msgstr "Abmelden"
#: bookwyrm/templates/layout.html:125 bookwyrm/templates/layout.html:126 #: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
#: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:6
#: bookwyrm/templates/notifications.html:10 #: bookwyrm/templates/notifications.html:10
msgid "Notifications" msgid "Notifications"
msgstr "Benachrichtigungen" msgstr "Benachrichtigungen"
#: bookwyrm/templates/layout.html:143 bookwyrm/templates/layout.html:147 #: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155
#: bookwyrm/templates/login.html:17 #: bookwyrm/templates/login.html:17
#: bookwyrm/templates/snippets/register_form.html:4 #: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:" msgid "Username:"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:152 bookwyrm/templates/login.html:10 #: bookwyrm/templates/layout.html:156
msgid "password"
msgstr "Passwort"
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Passwort vergessen?"
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33 #: bookwyrm/templates/login.html:33
msgid "Log in" msgid "Log in"
msgstr "Anmelden" msgstr "Anmelden"
#: bookwyrm/templates/layout.html:183 #: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server" msgid "About this server"
msgstr "Über diesen Server" msgstr "Über diesen Server"
#: bookwyrm/templates/layout.html:187 #: bookwyrm/templates/layout.html:195
msgid "Contact site admin" msgid "Contact site admin"
msgstr "Admin kontaktieren" msgstr "Admin kontaktieren"
#: bookwyrm/templates/layout.html:198 #: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site.name)s on <a href=\"%(site.support_link)s\" target=\"_blank\">%(site.support_title)s</a>"
msgstr ""
#: bookwyrm/templates/layout.html:206
msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>." msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>."
msgstr "BookWyrm ist open source Software. Du kannst dich auf <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> beteiligen oder etwas melden." msgstr "BookWyrm ist open source Software. Du kannst dich auf <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> beteiligen oder etwas melden."
@ -855,10 +878,6 @@ msgstr ""
msgid "Password:" msgid "Password:"
msgstr "Passwort:" msgstr "Passwort:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Passwort vergessen?"
#: bookwyrm/templates/login.html:49 #: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite" msgid "Contact an administrator to get an invite"
msgstr "Kontaktiere für eine Einladung eine*n Admin" msgstr "Kontaktiere für eine Einladung eine*n Admin"
@ -872,7 +891,7 @@ msgid "Not Found"
msgstr "Nicht gefunden" msgstr "Nicht gefunden"
#: bookwyrm/templates/notfound.html:9 #: bookwyrm/templates/notfound.html:9
msgid "The page your requested doesn't seem to exist!" msgid "The page you requested doesn't seem to exist!"
msgstr "Die Seite die du angefordert hast scheint nicht zu existieren!" msgstr "Die Seite die du angefordert hast scheint nicht zu existieren!"
#: bookwyrm/templates/notifications.html:14 #: bookwyrm/templates/notifications.html:14
@ -949,18 +968,18 @@ msgstr "hat dir eine Folgeanfrage geschickt"
#: bookwyrm/templates/notifications.html:90 #: bookwyrm/templates/notifications.html:90
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "hat deine <a href=\"%(related_path)s\">Bewertung von <em>%(book.title)s</em></a> geteilt" msgstr "hat deine <a href=\"%(related_path)s\">Bewertung von <em>%(book_title)s</em></a> geteilt"
#: bookwyrm/templates/notifications.html:92 #: bookwyrm/templates/notifications.html:92
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book_title)s</em></a>"
msgstr "hat deinen <a href=\"%(related_path)s\">Kommentar zu<em>%(book.title)s</em></a> geteilt" msgstr "hat deinen <a href=\"%(related_path)s\">Kommentar zu<em>%(book_title)s</em></a> geteilt"
#: bookwyrm/templates/notifications.html:94 #: bookwyrm/templates/notifications.html:94
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "hat dein <a href=\"%(related_path)s\">Zitat aus <em>%(book.title)s</em></a> geteilt" msgstr "hat dein <a href=\"%(related_path)s\">Zitat aus <em>%(book_title)s</em></a> geteilt"
#: bookwyrm/templates/notifications.html:96 #: bookwyrm/templates/notifications.html:96
#, python-format #, python-format
@ -1648,17 +1667,17 @@ msgstr "geteilt"
msgid "Reply" msgid "Reply"
msgstr "Antwort" msgstr "Antwort"
#: bookwyrm/templates/snippets/status/status_content.html:16 #: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:12 #: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more" msgid "Show more"
msgstr "Mehr anzeigen" msgstr "Mehr anzeigen"
#: bookwyrm/templates/snippets/status/status_content.html:23 #: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:18 #: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less" msgid "Show less"
msgstr "Weniger anzeigen" msgstr "Weniger anzeigen"
#: bookwyrm/templates/snippets/status/status_content.html:44 #: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window" msgid "Open image in new window"
msgstr "Bild in neuem Fenster öffnen" msgstr "Bild in neuem Fenster öffnen"
@ -1668,8 +1687,6 @@ msgid "More options"
msgstr "Mehr Optionen" msgstr "Mehr Optionen"
#: bookwyrm/templates/snippets/status/status_options.html:17 #: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status" msgid "Delete status"
msgstr "Post löschen" msgstr "Post löschen"
@ -1693,8 +1710,6 @@ msgstr "Mit \"%(tag.name)s\" markierte Bücher"
#: bookwyrm/templates/user/create_shelf_form.html:5 #: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22 #: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf" msgid "Create Shelf"
msgstr "Regal erstellen" msgstr "Regal erstellen"

View file

@ -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-03-02 21:36+0000\n" "POT-Creation-Date: 2021-03-04 22:24+0000\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"
@ -53,7 +53,7 @@ msgstr ""
msgid "%(value)s is not a valid username" msgid "%(value)s is not a valid username"
msgstr "" msgstr ""
#: bookwyrm/models/fields.py:164 #: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
msgid "username" msgid "username"
msgstr "" msgstr ""
@ -70,10 +70,14 @@ msgid "German"
msgstr "" msgstr ""
#: bookwyrm/settings.py:144 #: bookwyrm/settings.py:144
msgid "French" msgid "Spanish"
msgstr "" msgstr ""
#: bookwyrm/settings.py:145 #: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "" msgstr ""
@ -92,6 +96,8 @@ msgid "Books by %(name)s"
msgstr "" msgstr ""
#: bookwyrm/templates/book.html:21 #: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by" msgid "by"
msgstr "" msgstr ""
@ -419,7 +425,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr "" msgstr ""
#: bookwyrm/templates/feed/direct_messages.html:10 #: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79 #: bookwyrm/templates/layout.html:87
msgid "Direct Messages" msgid "Direct Messages"
msgstr "" msgstr ""
@ -525,7 +531,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "" msgstr ""
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94 #: bookwyrm/templates/layout.html:102
msgid "Import Books" msgid "Import Books"
msgstr "" msgstr ""
@ -648,55 +654,72 @@ msgstr ""
msgid "Feed" msgid "Feed"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:84 #: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14 #: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile" msgid "Profile"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:89 #: bookwyrm/templates/layout.html:97
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:103 #: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19 #: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3 #: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites" msgid "Invites"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:110 #: bookwyrm/templates/layout.html:118
msgid "Site Configuration" msgid "Site Configuration"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:117 #: bookwyrm/templates/layout.html:125
msgid "Log out" msgid "Log out"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:125 bookwyrm/templates/layout.html:126 #: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
#: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:6
#: bookwyrm/templates/notifications.html:10 #: bookwyrm/templates/notifications.html:10
msgid "Notifications" msgid "Notifications"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:143 bookwyrm/templates/layout.html:147 #: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155
#: bookwyrm/templates/login.html:17 #: bookwyrm/templates/login.html:17
#: bookwyrm/templates/snippets/register_form.html:4 #: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:" msgid "Username:"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:152 bookwyrm/templates/login.html:10 #: bookwyrm/templates/layout.html:156
msgid "password"
msgstr ""
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr ""
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33 #: bookwyrm/templates/login.html:33
msgid "Log in" msgid "Log in"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:183 #: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server" msgid "About this server"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:187 #: bookwyrm/templates/layout.html:195
msgid "Contact site admin" msgid "Contact site admin"
msgstr "" msgstr ""
#: bookwyrm/templates/layout.html:198 #: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site.name)s on <a href=\"%(site.support_link)s\" target=\"_blank\">%(site.support_title)s</a>"
msgstr ""
#: bookwyrm/templates/layout.html:206
msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>." msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>."
msgstr "" msgstr ""
@ -840,10 +863,6 @@ msgstr ""
msgid "Password:" msgid "Password:"
msgstr "" msgstr ""
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr ""
#: bookwyrm/templates/login.html:49 #: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite" msgid "Contact an administrator to get an invite"
msgstr "" msgstr ""
@ -857,7 +876,7 @@ msgid "Not Found"
msgstr "" msgstr ""
#: bookwyrm/templates/notfound.html:9 #: bookwyrm/templates/notfound.html:9
msgid "The page your requested doesn't seem to exist!" msgid "The page you requested doesn't seem to exist!"
msgstr "" msgstr ""
#: bookwyrm/templates/notifications.html:14 #: bookwyrm/templates/notifications.html:14
@ -934,17 +953,17 @@ msgstr ""
#: bookwyrm/templates/notifications.html:90 #: bookwyrm/templates/notifications.html:90
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "" msgstr ""
#: bookwyrm/templates/notifications.html:92 #: bookwyrm/templates/notifications.html:92
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book_title)s</em></a>"
msgstr "" msgstr ""
#: bookwyrm/templates/notifications.html:94 #: bookwyrm/templates/notifications.html:94
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "" msgstr ""
#: bookwyrm/templates/notifications.html:96 #: bookwyrm/templates/notifications.html:96
@ -1633,17 +1652,17 @@ msgstr ""
msgid "Reply" msgid "Reply"
msgstr "" msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:16 #: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:12 #: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more" msgid "Show more"
msgstr "" msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:23 #: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:18 #: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less" msgid "Show less"
msgstr "" msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:44 #: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window" msgid "Open image in new window"
msgstr "" msgstr ""

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -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-03-02 21:36+0000\n" "POT-Creation-Date: 2021-03-05 14:10+0000\n"
"PO-Revision-Date: 2021-03-02 12:37+0100\n" "PO-Revision-Date: 2021-03-02 12:37+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"
@ -55,7 +55,7 @@ msgstr ""
msgid "%(value)s is not a valid username" msgid "%(value)s is not a valid username"
msgstr "" msgstr ""
#: bookwyrm/models/fields.py:164 #: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
#, fuzzy #, fuzzy
#| msgid "Username:" #| msgid "Username:"
msgid "username" msgid "username"
@ -74,10 +74,14 @@ msgid "German"
msgstr "" msgstr ""
#: bookwyrm/settings.py:144 #: bookwyrm/settings.py:144
msgid "French" msgid "Spanish"
msgstr "" msgstr ""
#: bookwyrm/settings.py:145 #: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "" msgstr ""
@ -96,6 +100,8 @@ msgid "Books by %(name)s"
msgstr "Livres par %(name)s" msgstr "Livres par %(name)s"
#: bookwyrm/templates/book.html:21 #: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by" msgid "by"
msgstr "" msgstr ""
@ -431,15 +437,12 @@ msgid "Something went wrong! Sorry about that."
msgstr "Une erreur sest produite; désolé!" msgstr "Une erreur sest produite; désolé!"
#: bookwyrm/templates/feed/direct_messages.html:8 #: bookwyrm/templates/feed/direct_messages.html:8
#, fuzzy, python-format #, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>" msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr "Messages directs avec <a href=\"%(path)s\">%(username)s</a>" msgstr "Messages directs avec <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/feed/direct_messages.html:10 #: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79 #: bookwyrm/templates/layout.html:87
#, fuzzy
#| msgid "Send direct message"
msgid "Direct Messages" msgid "Direct Messages"
msgstr "Messages directs" msgstr "Messages directs"
@ -555,7 +558,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "Livres de %(username)s en %(year)s" msgstr "Livres de %(username)s en %(year)s"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94 #: bookwyrm/templates/layout.html:102
msgid "Import Books" msgid "Import Books"
msgstr "Importer des livres" msgstr "Importer des livres"
@ -610,37 +613,42 @@ msgstr "(Rechargez la page pour mettre à jour!"
#: bookwyrm/templates/import_status.html:35 #: bookwyrm/templates/import_status.html:35
msgid "Failed to load" msgid "Failed to load"
msgstr "Le chargement a échoué" msgstr "Items non importés"
#: bookwyrm/templates/import_status.html:59 #: bookwyrm/templates/import_status.html:42
#, python-format
msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import."
msgstr "Sauter en bas de liste pour sélectionner les %(failed_count)s items nayant pu être importés."
#: bookwyrm/templates/import_status.html:74
msgid "Select all" msgid "Select all"
msgstr "Tout sélectionner" msgstr "Tout sélectionner"
#: bookwyrm/templates/import_status.html:62 #: bookwyrm/templates/import_status.html:79
msgid "Retry items" msgid "Retry items"
msgstr "Essayer dimporter les objets sélectionnés de nouveau" msgstr "Essayer dimporter les items sélectionnés de nouveau"
#: bookwyrm/templates/import_status.html:84 #: bookwyrm/templates/import_status.html:101
msgid "Successfully imported" msgid "Successfully imported"
msgstr "Importation réussie" msgstr "Importation réussie"
#: bookwyrm/templates/import_status.html:88 #: bookwyrm/templates/import_status.html:105
#: bookwyrm/templates/lists/curate.html:14 #: bookwyrm/templates/lists/curate.html:14
msgid "Book" msgid "Book"
msgstr "Livre" msgstr "Livre"
#: bookwyrm/templates/import_status.html:91 #: bookwyrm/templates/import_status.html:108
#: bookwyrm/templates/snippets/create_status_form.html:10 #: bookwyrm/templates/snippets/create_status_form.html:10
#: bookwyrm/templates/snippets/shelf.html:10 #: bookwyrm/templates/snippets/shelf.html:10
msgid "Title" msgid "Title"
msgstr "Titre" msgstr "Titre"
#: bookwyrm/templates/import_status.html:94 #: bookwyrm/templates/import_status.html:111
#: bookwyrm/templates/snippets/shelf.html:11 #: bookwyrm/templates/snippets/shelf.html:11
msgid "Author" msgid "Author"
msgstr "Auteur ou autrice" msgstr "Auteur ou autrice"
#: bookwyrm/templates/import_status.html:117 #: bookwyrm/templates/import_status.html:134
msgid "Imported" msgid "Imported"
msgstr "Importé" msgstr "Importé"
@ -658,8 +666,6 @@ msgid "Sorry! This invite code is no longer valid."
msgstr "Cette invitation nest plus valide; désolé!" msgstr "Cette invitation nest plus valide; désolé!"
#: bookwyrm/templates/layout.html:33 #: bookwyrm/templates/layout.html:33
#, fuzzy
#| msgid "Search for a book"
msgid "Search for a book or user" msgid "Search for a book or user"
msgstr "Chercher un livre ou un compte" msgstr "Chercher un livre ou un compte"
@ -680,59 +686,76 @@ msgstr "Vos étagères"
msgid "Feed" msgid "Feed"
msgstr "Fil dactualité" msgstr "Fil dactualité"
#: bookwyrm/templates/layout.html:84 #: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14 #: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile" msgid "Profile"
msgstr "Profil" msgstr "Profil"
#: bookwyrm/templates/layout.html:89 #: bookwyrm/templates/layout.html:97
#, fuzzy #, fuzzy
#| msgid "Instance Settings" #| msgid "Instance Settings"
msgid "Settings" msgid "Settings"
msgstr "Paramètres de linstance" msgstr "Paramètres de linstance"
#: bookwyrm/templates/layout.html:103 #: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19 #: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3 #: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites" msgid "Invites"
msgstr "Invitations" msgstr "Invitations"
#: bookwyrm/templates/layout.html:110 #: bookwyrm/templates/layout.html:118
msgid "Site Configuration" msgid "Site Configuration"
msgstr "Configuration du site" msgstr "Configuration du site"
#: bookwyrm/templates/layout.html:117 #: bookwyrm/templates/layout.html:125
#, fuzzy
#| msgid "Log in"
msgid "Log out" msgid "Log out"
msgstr "Se déconnecter" msgstr "Se déconnecter"
#: bookwyrm/templates/layout.html:125 bookwyrm/templates/layout.html:126 #: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
#: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:6
#: bookwyrm/templates/notifications.html:10 #: bookwyrm/templates/notifications.html:10
msgid "Notifications" msgid "Notifications"
msgstr "Notifications" msgstr "Notifications"
#: bookwyrm/templates/layout.html:143 bookwyrm/templates/layout.html:147 #: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155
#: bookwyrm/templates/login.html:17 #: bookwyrm/templates/login.html:17
#: bookwyrm/templates/snippets/register_form.html:4 #: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:" msgid "Username:"
msgstr "Nom dutilisateur:" msgstr "Nom dutilisateur:"
#: bookwyrm/templates/layout.html:152 bookwyrm/templates/login.html:10 #: bookwyrm/templates/layout.html:156
#, fuzzy
#| msgid "Password:"
msgid "password"
msgstr "Mot de passe:"
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Mot de passe oublié?"
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33 #: bookwyrm/templates/login.html:33
msgid "Log in" msgid "Log in"
msgstr "Se connecter" msgstr "Se connecter"
#: bookwyrm/templates/layout.html:183 #: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server" msgid "About this server"
msgstr "À propos de ce serveur" msgstr "À propos de ce serveur"
#: bookwyrm/templates/layout.html:187 #: bookwyrm/templates/layout.html:195
msgid "Contact site admin" msgid "Contact site admin"
msgstr "Contacter ladministrateur du site" msgstr "Contacter ladministrateur du site"
#: bookwyrm/templates/layout.html:198 #: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site.name)s on <a href=\"%(site.support_link)s\" target=\"_blank\">%(site.support_title)s</a>"
msgstr ""
#: bookwyrm/templates/layout.html:206
msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>." msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>."
msgstr "Bookwyrm est un logiciel libre. Vous pouvez contribuer ou faire des rapports de bogues via <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>." msgstr "Bookwyrm est un logiciel libre. Vous pouvez contribuer ou faire des rapports de bogues via <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>."
@ -878,10 +901,6 @@ msgstr "Connexion"
msgid "Password:" msgid "Password:"
msgstr "Mot de passe:" msgstr "Mot de passe:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Mot de passe oublié?"
#: bookwyrm/templates/login.html:49 #: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite" msgid "Contact an administrator to get an invite"
msgstr "Contacter un administrateur pour obtenir une invitation" msgstr "Contacter un administrateur pour obtenir une invitation"
@ -895,7 +914,7 @@ msgid "Not Found"
msgstr "Introuvable" msgstr "Introuvable"
#: bookwyrm/templates/notfound.html:9 #: bookwyrm/templates/notfound.html:9
msgid "The page your requested doesn't seem to exist!" msgid "The page you requested doesn't seem to exist!"
msgstr "Il semblerait que la page que vous avez demandée nexiste pas!" msgstr "Il semblerait que la page que vous avez demandée nexiste pas!"
#: bookwyrm/templates/notifications.html:14 #: bookwyrm/templates/notifications.html:14
@ -903,74 +922,62 @@ msgid "Delete notifications"
msgstr "Supprimer les notifications" msgstr "Supprimer les notifications"
#: bookwyrm/templates/notifications.html:49 #: bookwyrm/templates/notifications.html:49
#, fuzzy, python-format #, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "favorited your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>" msgid "favorited your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "a ajouté votre <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a> à ses favoris" msgstr "a ajouté votre <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a> à ses favoris"
#: bookwyrm/templates/notifications.html:51 #: bookwyrm/templates/notifications.html:51
#, fuzzy, python-format #, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "favorited your <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>" msgid "favorited your <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr "a ajouté votre <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a> à ses favoris" msgstr "a ajouté votre <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a> à ses favoris"
#: bookwyrm/templates/notifications.html:53 #: bookwyrm/templates/notifications.html:53
#, fuzzy, python-format #, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "favorited your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>" msgid "favorited your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "a ajouté votre <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a> à ses favoris" msgstr "a ajouté votre <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a> à ses favoris"
#: bookwyrm/templates/notifications.html:55 #: bookwyrm/templates/notifications.html:55
#, fuzzy, python-format #, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "favorited your <a href=\"%(related_path)s\">status</a>" msgid "favorited your <a href=\"%(related_path)s\">status</a>"
msgstr "a ajouté votre <a href=\"%(related_path)s\">statut</a> à ses favoris" msgstr "a ajouté votre <a href=\"%(related_path)s\">statut</a> à ses favoris"
#: bookwyrm/templates/notifications.html:60 #: bookwyrm/templates/notifications.html:60
#, fuzzy, python-format #, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "mentioned you in a <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>" msgid "mentioned you in a <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "vous a mentionné dans sa <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a>" msgstr "vous a mentionné dans sa <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:62 #: bookwyrm/templates/notifications.html:62
#, fuzzy, python-format #, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "mentioned you in a <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>" msgid "mentioned you in a <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr "vous a mentionné dans son <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a>" msgstr "vous a mentionné dans son <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:64 #: bookwyrm/templates/notifications.html:64
#, fuzzy, python-format #, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "mentioned you in a <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>" msgid "mentioned you in a <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "vous a mentionné dans sa <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a>" msgstr "vous a mentionné dans sa <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:66 #: bookwyrm/templates/notifications.html:66
#, fuzzy, python-format #, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "mentioned you in a <a href=\"%(related_path)s\">status</a>" msgid "mentioned you in a <a href=\"%(related_path)s\">status</a>"
msgstr "vous a mentionné dans son <a href=\"%(related_path)s\">statut</a>" msgstr "vous a mentionné dans son <a href=\"%(related_path)s\">statut</a>"
#: bookwyrm/templates/notifications.html:71 #: bookwyrm/templates/notifications.html:71
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">review of <em>%(book_title)s</em></a>" msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">critique de <em>%(book_title)s</em></a>" msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">critique de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:73 #: bookwyrm/templates/notifications.html:73
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">comment on <em>%(book_title)s</em></a>" msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">commentaire sur <em>%(book_title)s</em></a>" msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">commentaire sur <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:75 #: bookwyrm/templates/notifications.html:75
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">quote from <em>%(book_title)s</em></a>" msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">citation de <em>%(book_title)s</em></a>" msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">citation de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:77 #: bookwyrm/templates/notifications.html:77
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>" msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">statut</a>" msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">statut</a>"
@ -983,38 +990,32 @@ msgid "sent you a follow request"
msgstr "vous a envoyé une demande dabonnement" msgstr "vous a envoyé une demande dabonnement"
#: bookwyrm/templates/notifications.html:90 #: bookwyrm/templates/notifications.html:90
#, fuzzy, python-format #, python-format
#| msgid "boosted your <a href=\"%(related_path)s\">%(preview_name)s</a>" msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book.title)s</em></a>"
msgstr "a partagé votre <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a>" msgstr "a partagé votre <a href=\"%(related_path)s\">critique de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:92 #: bookwyrm/templates/notifications.html:92
#, fuzzy, python-format #, python-format
#| msgid "boosted your <a href=\"%(related_path)s\">%(preview_name)s</a>" msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book_title)s</em></a>"
msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book.title)s</em></a>"
msgstr "a partagé votre <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a>" msgstr "a partagé votre <a href=\"%(related_path)s\">commentaire sur <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:94 #: bookwyrm/templates/notifications.html:94
#, fuzzy, python-format #, python-format
#| msgid "boosted your <a href=\"%(related_path)s\">%(preview_name)s</a>" msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book.title)s</em></a>"
msgstr "a partagé votre <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a>" msgstr "a partagé votre <a href=\"%(related_path)s\">citation de <em>%(book_title)s</em></a>"
#: bookwyrm/templates/notifications.html:96 #: bookwyrm/templates/notifications.html:96
#, fuzzy, python-format #, python-format
#| msgid "boosted your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "boosted your <a href=\"%(related_path)s\">status</a>" msgid "boosted your <a href=\"%(related_path)s\">status</a>"
msgstr "a partagé votre <a href=\"%(related_path)s\">statut</a>" msgstr "a partagé votre <a href=\"%(related_path)s\">statut</a>"
#: bookwyrm/templates/notifications.html:100 #: bookwyrm/templates/notifications.html:100
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid " added <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list \"<a href=\"%(list_path)s\">%(list_name)s</a>\"" msgid " added <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list \"<a href=\"%(list_path)s\">%(list_name)s</a>\""
msgstr " a ajouté <em><a href=\"%(book_path)s\">%(book_title)s</a></em> à votre liste « <a href=\"%(list_path)s\">%(list_name)s</a> »" msgstr " a ajouté <em><a href=\"%(book_path)s\">%(book_title)s</a></em> à votre liste « <a href=\"%(list_path)s\">%(list_name)s</a> »"
#: bookwyrm/templates/notifications.html:102 #: bookwyrm/templates/notifications.html:102
#, fuzzy, python-format #, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
msgid " suggested adding <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list \"<a href=\"%(list_path)s/curate\">%(list_name)s</a>\"" msgid " suggested adding <em><a href=\"%(book_path)s\">%(book_title)s</a></em> to your list \"<a href=\"%(list_path)s/curate\">%(list_name)s</a>\""
msgstr " a suggégré lajout de <em><a href=\"%(book_path)s\">%(book_title)s</a></em> à votre liste « <a href=\"%(list_path)s/curate\">%(list_name)s</a> »" msgstr " a suggégré lajout de <em><a href=\"%(book_path)s\">%(book_title)s</a></em> à votre liste « <a href=\"%(list_path)s/curate\">%(list_name)s</a> »"
@ -1108,8 +1109,6 @@ msgid "Relationships"
msgstr "Relations" msgstr "Relations"
#: bookwyrm/templates/search_results.html:4 #: bookwyrm/templates/search_results.html:4
#, fuzzy
#| msgid "Search Results for \"%(query)s\""
msgid "Search Results" msgid "Search Results"
msgstr "Résultats de recherche" msgstr "Résultats de recherche"
@ -1158,8 +1157,6 @@ msgid "No lists found for \"%(query)s\""
msgstr "Aucune liste trouvée pour « %(query)s»" msgstr "Aucune liste trouvée pour « %(query)s»"
#: bookwyrm/templates/settings/admin_layout.html:4 #: bookwyrm/templates/settings/admin_layout.html:4
#, fuzzy
#| msgid "Registration"
msgid "Administration" msgid "Administration"
msgstr "Administration" msgstr "Administration"
@ -1313,8 +1310,7 @@ msgid "Un-block"
msgstr "Débloquer" msgstr "Débloquer"
#: bookwyrm/templates/snippets/book_titleby.html:3 #: bookwyrm/templates/snippets/book_titleby.html:3
#, fuzzy, python-format #, python-format
#| msgid "Editions of <a href=\"%(work_path)s\">\"%(work_title)s\"</a>"
msgid "<a href=\"%(path)s\">%(title)s</a> by " msgid "<a href=\"%(path)s\">%(title)s</a> by "
msgstr "<a href=\"%(path)s\">%(title)s</a> par " msgstr "<a href=\"%(path)s\">%(title)s</a> par "
@ -1363,8 +1359,6 @@ msgid "No rating"
msgstr "Aucune note" msgstr "Aucune note"
#: bookwyrm/templates/snippets/create_status_form.html:54 #: bookwyrm/templates/snippets/create_status_form.html:54
#, fuzzy
#| msgid "Spoiler alert:"
msgid "Include spoiler alert" msgid "Include spoiler alert"
msgstr "Afficher une alerte spoiler" msgstr "Afficher une alerte spoiler"
@ -1704,17 +1698,17 @@ msgstr "partagé"
msgid "Reply" msgid "Reply"
msgstr "Répondre" msgstr "Répondre"
#: bookwyrm/templates/snippets/status/status_content.html:16 #: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:12 #: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more" msgid "Show more"
msgstr "Déplier" msgstr "Déplier"
#: bookwyrm/templates/snippets/status/status_content.html:23 #: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:18 #: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less" msgid "Show less"
msgstr "Replier" msgstr "Replier"
#: bookwyrm/templates/snippets/status/status_content.html:44 #: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window" msgid "Open image in new window"
msgstr "Ouvrir limage dans une nouvelle fenêtre" msgstr "Ouvrir limage dans une nouvelle fenêtre"
@ -1724,8 +1718,6 @@ msgid "More options"
msgstr "Plus doptions" msgstr "Plus doptions"
#: bookwyrm/templates/snippets/status/status_options.html:17 #: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status" msgid "Delete status"
msgstr "Supprimer le statut" msgstr "Supprimer le statut"
@ -1749,8 +1741,6 @@ msgstr "Livres tagués « %(tag.name)s»"
#: bookwyrm/templates/user/create_shelf_form.html:5 #: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22 #: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf" msgid "Create Shelf"
msgstr "Créer létagère" msgstr "Créer létagère"
@ -1764,8 +1754,6 @@ msgstr "Mettre létagère à jour"
#: bookwyrm/templates/user/followers.html:7 #: bookwyrm/templates/user/followers.html:7
#: bookwyrm/templates/user/following.html:7 bookwyrm/templates/user/user.html:9 #: bookwyrm/templates/user/following.html:7 bookwyrm/templates/user/user.html:9
#, fuzzy
#| msgid "User profile"
msgid "User Profile" msgid "User Profile"
msgstr "Profil" msgstr "Profil"
@ -1784,8 +1772,6 @@ msgid "%(username)s isn't following any users"
msgstr "%(username)s nest abonné(e) à personne" msgstr "%(username)s nest abonné(e) à personne"
#: bookwyrm/templates/user/lists.html:9 #: bookwyrm/templates/user/lists.html:9
#, fuzzy
#| msgid "Your lists"
msgid "Your Lists" msgid "Your Lists"
msgstr "Vos listes" msgstr "Vos listes"
@ -1800,14 +1786,11 @@ msgid "Create list"
msgstr "Créer une liste" msgstr "Créer une liste"
#: bookwyrm/templates/user/shelf.html:9 #: bookwyrm/templates/user/shelf.html:9
#, fuzzy
#| msgid "Your shelves"
msgid "Your Shelves" msgid "Your Shelves"
msgstr "Vos étagères" msgstr "Vos étagères"
#: bookwyrm/templates/user/shelf.html:11 #: bookwyrm/templates/user/shelf.html:11
#, fuzzy, python-format #, python-format
#| msgid "%(username)s has no followers"
msgid "%(username)s: Shelves" msgid "%(username)s: Shelves"
msgstr "%(username)s: Étagères" msgstr "%(username)s: Étagères"
@ -1816,8 +1799,6 @@ msgid "Create shelf"
msgstr "Créer létagère" msgstr "Créer létagère"
#: bookwyrm/templates/user/shelf.html:54 #: bookwyrm/templates/user/shelf.html:54
#, fuzzy
#| msgid "Edit Shelf"
msgid "Edit shelf" msgid "Edit shelf"
msgstr "Modifier létagère" msgstr "Modifier létagère"

Binary file not shown.

View file

@ -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-03-02 21:36+0000\n" "POT-Creation-Date: 2021-03-04 22:24+0000\n"
"PO-Revision-Date: 2021-03-02 10:35+0000\n" "PO-Revision-Date: 2021-03-02 10:35+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"
@ -55,11 +55,9 @@ msgstr ""
msgid "%(value)s is not a valid username" msgid "%(value)s is not a valid username"
msgstr "" msgstr ""
#: bookwyrm/models/fields.py:164 #: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
#, fuzzy
#| msgid "Username:"
msgid "username" msgid "username"
msgstr "用户名:" msgstr "用户名"
#: bookwyrm/models/fields.py:169 #: bookwyrm/models/fields.py:169
msgid "A user with that username already exists." msgid "A user with that username already exists."
@ -74,10 +72,14 @@ msgid "German"
msgstr "" msgstr ""
#: bookwyrm/settings.py:144 #: bookwyrm/settings.py:144
msgid "French" msgid "Spanish"
msgstr "" msgstr ""
#: bookwyrm/settings.py:145 #: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "" msgstr ""
@ -96,6 +98,8 @@ msgid "Books by %(name)s"
msgstr "%(name)s 所著的书" msgstr "%(name)s 所著的书"
#: bookwyrm/templates/book.html:21 #: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by" msgid "by"
msgstr "" msgstr ""
@ -427,7 +431,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信" msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信"
#: bookwyrm/templates/feed/direct_messages.html:10 #: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79 #: bookwyrm/templates/layout.html:87
msgid "Direct Messages" msgid "Direct Messages"
msgstr "私信" msgstr "私信"
@ -537,7 +541,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "%(username)s 在 %(year)s 的书目" msgstr "%(username)s 在 %(year)s 的书目"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94 #: bookwyrm/templates/layout.html:102
msgid "Import Books" msgid "Import Books"
msgstr "导入书目" msgstr "导入书目"
@ -660,55 +664,72 @@ msgstr "你的书架"
msgid "Feed" msgid "Feed"
msgstr "动态" msgstr "动态"
#: bookwyrm/templates/layout.html:84 #: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14 #: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile" msgid "Profile"
msgstr "个人资料" msgstr "个人资料"
#: bookwyrm/templates/layout.html:89 #: bookwyrm/templates/layout.html:97
msgid "Settings" msgid "Settings"
msgstr "设置" msgstr "设置"
#: bookwyrm/templates/layout.html:103 #: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19 #: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3 #: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites" msgid "Invites"
msgstr "邀请" msgstr "邀请"
#: bookwyrm/templates/layout.html:110 #: bookwyrm/templates/layout.html:118
msgid "Site Configuration" msgid "Site Configuration"
msgstr "站点配置" msgstr "站点配置"
#: bookwyrm/templates/layout.html:117 #: bookwyrm/templates/layout.html:125
msgid "Log out" msgid "Log out"
msgstr "登出" msgstr "登出"
#: bookwyrm/templates/layout.html:125 bookwyrm/templates/layout.html:126 #: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
#: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:6
#: bookwyrm/templates/notifications.html:10 #: bookwyrm/templates/notifications.html:10
msgid "Notifications" msgid "Notifications"
msgstr "通知" msgstr "通知"
#: bookwyrm/templates/layout.html:143 bookwyrm/templates/layout.html:147 #: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155
#: bookwyrm/templates/login.html:17 #: bookwyrm/templates/login.html:17
#: bookwyrm/templates/snippets/register_form.html:4 #: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:" msgid "Username:"
msgstr "用户名:" msgstr "用户名:"
#: bookwyrm/templates/layout.html:152 bookwyrm/templates/login.html:10 #: bookwyrm/templates/layout.html:156
msgid "password"
msgstr "密码"
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "忘记了密码?"
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33 #: bookwyrm/templates/login.html:33
msgid "Log in" msgid "Log in"
msgstr "登录" msgstr "登录"
#: bookwyrm/templates/layout.html:183 #: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server" msgid "About this server"
msgstr "关于本服务器" msgstr "关于本服务器"
#: bookwyrm/templates/layout.html:187 #: bookwyrm/templates/layout.html:195
msgid "Contact site admin" msgid "Contact site admin"
msgstr "联系站点管理员" msgstr "联系站点管理员"
#: bookwyrm/templates/layout.html:198 #: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site.name)s on <a href=\"%(site.support_link)s\" target=\"_blank\">%(site.support_title)s</a>"
msgstr ""
#: bookwyrm/templates/layout.html:206
msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>." msgid "BookWyrm is open source software. You can contribute or report issues on <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a>."
msgstr "BookWyrm 是开源软件。你可以在<a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> 贡献或报告问题。" msgstr "BookWyrm 是开源软件。你可以在<a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> 贡献或报告问题。"
@ -854,10 +875,6 @@ msgstr "登录"
msgid "Password:" msgid "Password:"
msgstr "密码:" msgstr "密码:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "忘记了密码?"
#: bookwyrm/templates/login.html:49 #: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite" msgid "Contact an administrator to get an invite"
msgstr "联系管理员以取得邀请" msgstr "联系管理员以取得邀请"
@ -871,7 +888,7 @@ msgid "Not Found"
msgstr "未找到" msgstr "未找到"
#: bookwyrm/templates/notfound.html:9 #: bookwyrm/templates/notfound.html:9
msgid "The page your requested doesn't seem to exist!" msgid "The page you requested doesn't seem to exist!"
msgstr "你请求的页面似乎并不存在!" msgstr "你请求的页面似乎并不存在!"
#: bookwyrm/templates/notifications.html:14 #: bookwyrm/templates/notifications.html:14
@ -948,18 +965,18 @@ msgstr "向你发送了关注请求"
#: bookwyrm/templates/notifications.html:90 #: bookwyrm/templates/notifications.html:90
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book.title)s</em> 的书评</a>" msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book_title)s</em> 的书评</a>"
#: bookwyrm/templates/notifications.html:92 #: bookwyrm/templates/notifications.html:92
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">comment on<em>%(book_title)s</em></a>"
msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book.title)s</em> 的评论</a>" msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book_title)s</em> 的评论</a>"
#: bookwyrm/templates/notifications.html:94 #: bookwyrm/templates/notifications.html:94
#, python-format #, python-format
msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book.title)s</em></a>" msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book.title)s</em> 的引用</a>" msgstr "转发了你的 <a href=\"%(related_path)s\">对 <em>%(book_title)s</em> 的引用</a>"
#: bookwyrm/templates/notifications.html:96 #: bookwyrm/templates/notifications.html:96
#, python-format #, python-format
@ -989,7 +1006,6 @@ msgstr "你什么也没错过!"
#: bookwyrm/templates/password_reset.html:10 #: bookwyrm/templates/password_reset.html:10
#: bookwyrm/templates/password_reset_request.html:4 #: bookwyrm/templates/password_reset_request.html:4
#: bookwyrm/templates/password_reset_request.html:10 #: bookwyrm/templates/password_reset_request.html:10
#, fuzzy
msgid "Reset Password" msgid "Reset Password"
msgstr "重设密码" msgstr "重设密码"
@ -1647,17 +1663,17 @@ msgstr "转发了"
msgid "Reply" msgid "Reply"
msgstr "回复" msgstr "回复"
#: bookwyrm/templates/snippets/status/status_content.html:16 #: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:12 #: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more" msgid "Show more"
msgstr "显示更多" msgstr "显示更多"
#: bookwyrm/templates/snippets/status/status_content.html:23 #: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:18 #: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less" msgid "Show less"
msgstr "显示更少" msgstr "显示更少"
#: bookwyrm/templates/snippets/status/status_content.html:44 #: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window" msgid "Open image in new window"
msgstr "在新窗口中打开图像" msgstr "在新窗口中打开图像"
@ -1667,8 +1683,6 @@ msgid "More options"
msgstr "更多选项" msgstr "更多选项"
#: bookwyrm/templates/snippets/status/status_options.html:17 #: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status" msgid "Delete status"
msgstr "删除发文" msgstr "删除发文"
@ -1692,8 +1706,6 @@ msgstr "标有 \"%(tag.name)s\" 标签的书"
#: bookwyrm/templates/user/create_shelf_form.html:5 #: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22 #: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf" msgid "Create Shelf"
msgstr "创建书架" msgstr "创建书架"