Merge branch 'main' into create-book

This commit is contained in:
Mouse Reeve 2021-03-07 15:49:00 -08:00
commit 6d9c024e0e
77 changed files with 3191 additions and 650 deletions

View file

@ -2,15 +2,12 @@ FROM python:3.9
ENV PYTHONUNBUFFERED 1
RUN mkdir /app
RUN mkdir /app/static
RUN mkdir /app/images
RUN mkdir /app /app/static /app/images
WORKDIR /app
COPY requirements.txt /app/
RUN pip install -r requirements.txt
RUN apt-get update && apt-get install -y gettext libgettextpo-dev
RUN pip install -r requirements.txt --no-cache-dir
RUN apt-get update && apt-get install -y gettext libgettextpo-dev && apt-get clean
COPY ./bookwyrm /app
COPY ./celerywyrm /app
COPY ./bookwyrm ./celerywyrm /app/

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).
### 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
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
```
### 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.
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
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
./bw-dev compilemessages
```

View file

@ -102,7 +102,7 @@ class ActivityObject:
if allow_create and \
hasattr(model, 'ignore_activity') and \
model.ignore_activity(self):
return None
raise ActivitySerializerError()
# check for an existing instance
instance = instance or model.find_existing(self.serialize())

View file

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

View file

@ -26,6 +26,7 @@ class AbstractMinimalConnector(ABC):
'books_url',
'covers_url',
'search_url',
'isbn_search_url',
'max_query_count',
'name',
'identifier',
@ -61,6 +62,30 @@ class AbstractMinimalConnector(ABC):
results.append(self.format_search_result(doc))
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
def get_or_create_book(self, remote_id):
''' pull up a book record by whatever means possible '''
@ -73,6 +98,14 @@ class AbstractMinimalConnector(ABC):
def format_search_result(self, search_result):
''' 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):
''' generic book data connector '''

View file

@ -19,3 +19,11 @@ class Connector(AbstractMinimalConnector):
def format_search_result(self, search_result):
search_result['connector'] = self
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 '''
import importlib
import re
from urllib.parse import urlparse
from requests import HTTPError
@ -15,9 +16,27 @@ class ConnectorException(HTTPError):
def search(query, min_confidence=0.1):
''' find books based on arbitary keywords '''
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)
result_index = set()
for connector in get_connectors():
result_set = None
if maybe_isbn:
# Search on ISBN
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):
@ -41,6 +60,12 @@ def local_search(query, min_confidence=0.1, raw=False):
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):
''' search until you find a result that fits '''
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):
''' query openlibrary for editions of a work '''
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)
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):
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):
pass
@ -59,6 +97,10 @@ class Connector(AbstractConnector):
def get_authors_from_data(self, data):
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):
''' it's already in the right format, don't even worry about it '''
return data

View file

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

@ -449,7 +449,7 @@ def broadcast_task(sender_id, activity, recipients):
for recipient in recipients:
try:
sign_and_send(sender, activity, recipient)
except (HTTPError, SSLError) as e:
except (HTTPError, SSLError, ConnectionError) as e:
logger.exception(e)

View file

@ -37,6 +37,10 @@ class BookDataModel(ObjectMixin, BookWyrmModel):
self.remote_id = None
return super().save(*args, **kwargs)
def broadcast(self, activity, sender, software='bookwyrm'):
''' only send book data updates to other bookwyrm instances '''
super().broadcast(activity, sender, software=software)
class Book(BookDataModel):
''' a generic book, which can mean either an edition or a work '''
@ -91,7 +95,7 @@ class Book(BookDataModel):
@property
def alt_text(self):
''' image alt test '''
text = '%s cover' % self.title
text = '%s' % self.title
if self.edition_info:
text += ' (%s)' % self.edition_info
return text

View file

@ -22,6 +22,7 @@ class Connector(BookWyrmModel):
books_url = models.CharField(max_length=255)
covers_url = models.CharField(max_length=255)
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
max_query_count = models.IntegerField(null=True, blank=True)

View file

@ -7,6 +7,7 @@ from bookwyrm import activitypub
from .activitypub_mixin import ActivityMixin
from .base_model import BookWyrmModel
from . import fields
from .status import Status
class Favorite(ActivityMixin, BookWyrmModel):
''' fav'ing a post '''
@ -17,6 +18,11 @@ class Favorite(ActivityMixin, BookWyrmModel):
activity_serializer = activitypub.Like
@classmethod
def ignore_activity(cls, activity):
''' don't bother with incoming favs of unknown statuses '''
return not Status.objects.filter(remote_id=activity.object).exists()
def save(self, *args, **kwargs):
''' update user active time '''
self.user.last_active_date = timezone.now()

View file

@ -3,7 +3,7 @@ import re
from urllib.parse import urlparse
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.db import models
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
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
self.key_pair = KeyPair.objects.create(
remote_id='%s/#main-key' % self.remote_id)

View file

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

View file

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

View file

@ -8,9 +8,12 @@ window.onload = function() {
Array.from(document.getElementsByClassName('interaction'))
.forEach(t => t.onsubmit = interact);
// select all
Array.from(document.getElementsByClassName('select-all'))
.forEach(t => t.onclick = selectAll);
// Toggle all checkboxes.
document
.querySelectorAll('[data-action="toggle-all"]')
.forEach(input => {
input.addEventListener('change', toggleAllCheckboxes);
});
// tab groups
Array.from(document.getElementsByClassName('tab-group'))
@ -136,9 +139,20 @@ function interact(e) {
.forEach(t => addRemoveClass(t, 'hidden', t.className.indexOf('hidden') == -1));
}
function selectAll(e) {
e.target.parentElement.parentElement.querySelectorAll('[type="checkbox"]')
.forEach(t => t.checked=true);
/**
* Toggle all descendant checkboxes of a target.
*
* 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) {

View file

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

View file

@ -5,7 +5,7 @@
{% block dropdown-trigger %}{% endblock %}
</button>
<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 %}
</ul>
</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-card">
<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 %}
</h2>
{% include 'snippets/toggle/toggle_button.html' with label="close" class="delete" nonbutton=True %}
@ -18,7 +25,6 @@
</footer>
{% block modal-form-close %}{% endblock %}
</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 %}
</div>

View file

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

View file

@ -1,4 +1,5 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% if book %}
<div class="columns">
<div class="column is-narrow">
@ -8,7 +9,7 @@
<div class="column">
<h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
{% 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 %}
{% if book|book_description %}
<blockquote class="content">{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}</blockquote>

View file

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

View file

@ -6,13 +6,13 @@
<h1 class="title">{% blocktrans %}{{ tab_title }} Timeline{% endblocktrans %}</h1>
<div class="tabs">
<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>
</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>
</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>
</li>
</ul>

View file

@ -4,7 +4,7 @@
{% block panel %}
<header class="block">
<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>
</a>
</header>

View file

@ -5,7 +5,7 @@
{% block title %}{% trans "Import Status" %}{% endblock %}
{% block content %}
{% block content %}{% spaceless %}
<div class="block">
<h1 class="title">{% trans "Import Status" %}</h1>
@ -36,8 +36,19 @@
{% if not job.retry %}
<form name="retry" action="/import/{{ job.id }}" method="post">
{% csrf_token %}
{% 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>
<fieldset>
{% for item in failed_items %}
<li class="pb-1">
<input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}">
@ -51,15 +62,28 @@
</p>
</li>
{% endfor %}
</fieldset>
</ul>
<div class="block pt-1 select-all">
<label class="label">
<input type="checkbox" class="checkbox">
</fieldset>
<fieldset class="mt-3">
<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" %}
</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 %}
<ul>
{% for item in failed_items %}
@ -123,4 +147,4 @@
</table>
</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">
</head>
<body>
<nav class="navbar container" role="navigation" aria-label="main navigation">
<nav class="navbar container" aria-label="main navigation">
<div class="navbar-brand">
<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">
@ -69,10 +69,18 @@
<div class="navbar-end">
{% if request.user.is_authenticated %}
<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/username.html' with user=request.user %}
</p></div>
<span class="ml-2">{{ user.display_name }}</span>
</a>
<ul class="navbar-dropdown" id="navbar-dropdown">
<li>
<a href="/direct-messages" class="navbar-item">
@ -95,7 +103,7 @@
</a>
</li>
{% if perms.bookwyrm.create_invites or perms.bookwyrm.edit_instance_settings%}
<hr class="navbar-divider">
<li class="navbar-divider" role="presentation"></li>
{% endif %}
{% if perms.bookwyrm.create_invites %}
<li>
@ -111,7 +119,7 @@
</a>
</li>
{% endif %}
<hr class="navbar-divider">
<li class="navbar-divider" role="presentation"></li>
<li>
<a href="/logout" class="navbar-item">
{% trans 'Log out' %}
@ -141,12 +149,12 @@
<div class="columns is-variable is-1">
<div class="column">
<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 class="column">
<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">
<p class="help"><a href="/password-reset">Forgot your password?</a></p>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="{% trans 'password' %}">
<p class="help"><a href="/password-reset">{% trans "Forgot your password?" %}</a></p>
</div>
<div class="column is-narrow">
<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 != '/' %}
<div class="column is-narrow">
<a href="/" class="button is-link">
Join
{% trans "Join" %}
</a>
</div>
{% endif %}
@ -191,7 +199,7 @@
{% if site.support_link %}
<div class="column">
<span class="icon icon-heart"></span>
Support {{ site.name }} on <a href="{{ site.support_link }}" target="_blank">{{ site.support_title }}</a>
{% blocktrans with site_name=site.name support_link=site.support_link support_title=site.support_title %}Support {{ site_name }} on <a href="{{ support_link }}" target="_blank">{{ support_title }}</a>{% endblocktrans %}
</div>
{% endif %}
<div class="column">

View file

@ -0,0 +1,10 @@
{% load i18n %}
{% spaceless %}
{% if list.curation != 'open' %}
{% blocktrans with username=list.user.display_name path=list.user.local_path %}Created and curated by <a href="{{ path }}">{{ username }}</a>{% endblocktrans %}
{% else %}
{% blocktrans with username=list.user.display_name path=list.user.local_path %}Created by <a href="{{ path }}">{{ username }}</a>{% endblocktrans %}
{% endif %}
{% endspaceless %}

View file

@ -24,7 +24,7 @@
{% include 'snippets/book_titleby.html' with book=item.book %}
</td>
<td>
{% include 'snippets/username.html' with user=item.user %}
<a href="{{ item.user.local_path }}">{{ item.user.display_name }}</a>
</td>
<td>
<div class="field has-addons">

View file

@ -1,5 +1,4 @@
{% load bookwyrm_tags %}
{% load i18n %}
<div class="columns is-multiline">
{% for list in lists %}
<div class="column is-one-quarter">
@ -16,7 +15,9 @@
</div>
<div class="card-content is-flex-grow-0">
{% if list.description %}{{ list.description | to_markdown | safe | truncatewords_html:20 }}{% endif %}
<p class="subtitle help">{% if list.curation != 'open' %}{% trans "Created and curated by" %}{% else %}{% trans "Created by" %}{% endif %} {% include 'snippets/username.html' with user=list.user %}</p>
<p class="subtitle help">
{% include 'lists/created_text.html' with list=list %}
</p>
</div>
</div>
</div>

View file

@ -8,8 +8,9 @@
<header class="columns content is-mobile">
<div class="column">
<h1 class="title">{{ list.name }} <span class="subtitle">{% include 'snippets/privacy-icons.html' with item=list %}</span></h1>
<p class="subtitle help">{% if list.curation != 'open' %}{% trans "Created and curated by" %}{% else %}{% trans "Created by" %} {% include 'snippets/username.html' with user=list.user %}</p>
{% endif %}
<p class="subtitle help">
{% include 'lists/created_text.html' with list=list %}
</p>
{% include 'snippets/trimmed_text.html' with full=list.description %}
</div>
{% if request.user == list.user %}

View file

@ -6,6 +6,6 @@
{% block content %}
<div class="block">
<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>
{% endblock %}

View file

@ -42,8 +42,10 @@
<p>
{# DESCRIPTION #}
{% if notification.related_user %}
<a href="{{ notification.related_user.local_path }}">
{% include 'snippets/avatar.html' with user=notification.related_user %}
{% include 'snippets/username.html' with user=notification.related_user %}
{{ notification.related_user.display_name }}
</a>
{% if notification.notification_type == 'FAVORITE' %}
{% if related_status.status_type == 'Review' %}
{% blocktrans with book_title=related_status.book.title related_path=related_status.local_path %}favorited your <a href="{{ related_path }}">review of <em>{{ book_title }}</em></a>{% endblocktrans %}
@ -87,11 +89,11 @@
</div>
{% elif notification.notification_type == 'BOOST' %}
{% 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' %}
{% 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' %}
{% 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 %}
{% blocktrans with related_path=related_status.local_path %}boosted your <a href="{{ related_path }}">status</a>{% endblocktrans %}
{% endif %}
@ -114,7 +116,9 @@
<div class="columns">
<div class="column">
{% 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 %}
<a href="{{ related_status.local_path }}">{{ related_status.quote | safe | truncatewords_html:10 }}</a>
{% elif related_status.rating %}

View file

@ -15,7 +15,7 @@
{% for user in request.user.blocks.all %}
<li class="is-flex">
<p>
{% include 'snippets/avatar.html' with user=user %} {% include 'snippets/username.html' with user=user %}
<a href="{{ user.local_path }}">{% include 'snippets/avatar.html' with user=user %} {{ user.display_name }}</a>
</p>
<p class="mr-2">
{% include 'snippets/block_button.html' with user=user %}

View file

@ -79,8 +79,10 @@
<ul>
{% for result in user_results %}
<li class="block">
{% include 'snippets/avatar.html' with user=result %}</h2>
{% include 'snippets/username.html' with user=result show_full=True %}</h2>
<a href="{{ result.local_path }}">
{% include 'snippets/avatar.html' with user=result %}
{{ result.display_name }}
</a> ({{ result.username }})
{% include 'snippets/follow_button.html' with user=result %}
</li>
{% endfor %}

View file

@ -1,3 +1,3 @@
{% 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">
<img class="book-cover" src="/static/images/no_cover.jpg" alt="No cover">
<div>
<p>{{ book.title }}</p>
<p>({{ book.edition_info }})</p>
<p>{{ book.alt_text }}</p>
</div>
</div>
{% endif %}

View file

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

View file

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

View file

@ -2,8 +2,10 @@
{% load i18n %}
{% if not status.deleted %}
{% if status.status_type == 'Announce' %}
<a href="{{ status.user.local_path }}">
{% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %}
{{ status.user.display_name }}
</a>
{% trans "boosted" %}
{% include 'snippets/status/status_body.html' with status=status|boosted_status %}
{% else %}

View file

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

View file

@ -1,7 +1,9 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %}
<a href="{{ status.user.local_path }}">
{% include 'snippets/avatar.html' with user=status.user ariaHide="true" %}
{{ status.user.display_name }}
</a>
{% if status.status_type == 'GeneratedNote' %}
{{ status.content | safe }}
@ -15,7 +17,17 @@
{% trans "quoted" %}
{% elif status.reply_parent %}
{% with parent_status=status|parent %}
replied to {% include 'snippets/username.html' with user=parent_status.user possessive=True %} <a href="{{parent_status.remote_id }}">{% if parent_status.status_type == 'GeneratedNote' %}update{% else %}{{ parent_status.status_type | lower }}{% endif %}</a>
{% if parent_status.status_type == 'Review' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">review</a>{% endblocktrans %}
{% elif parent_status.status_type == 'Comment' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">comment</a>{% endblocktrans %}
{% elif parent_status.status_type == 'Quotation' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">quote</a>{% endblocktrans %}
{% else %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">status</a>{% endblocktrans %}
{% endif %}
{% endwith %}
{% endif %}
{% if status.book %}

View file

@ -8,19 +8,29 @@
{% with full|to_markdown|safe|truncatewords_html:60 as trimmed %}
{% if trimmed != full %}
<div id="hide-full-{{ uuid }}">
<div class="content" id="trimmed-{{ uuid }}"><span dir="auto">{{ trimmed }}</span>
<div class="content" id="trimmed-{{ uuid }}">
<p dir="auto">{{ trimmed }}</p>
<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 id="full-{{ uuid }}" class="hidden">
<div class="content"><span dir="auto">{{ full }}</span>
<div class="content">
<div dir="auto">{{ full }}</div>
<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>
{% else %}
<div class="content"><span dir="auto">{{ full }}</span></div>
<div class="content">
<div dir="auto">{{ full }}</div>
</div>
{% endif %}
{% endwith %}

View file

@ -1,2 +0,0 @@
{% 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 %}

View file

@ -11,19 +11,22 @@
{% block panel %}
<div class="block">
<h2 class="title">{% trans "Followers" %}</h2>
{% for followers in followers %}
{% for follower in followers %}
<div class="block columns">
<div class="column">
{% include 'snippets/avatar.html' with user=followers %}
{% include 'snippets/username.html' with user=followers show_full=True %}
<a href="{{ follower.local_path }}">
{% include 'snippets/avatar.html' with user=follower %}
{{ follower.display_name }}
</a>
({{ follower.username }})
</div>
<div class="column is-narrow">
{% include 'snippets/follow_button.html' with user=followers %}
{% include 'snippets/follow_button.html' with user=follower %}
</div>
</div>
{% endfor %}
{% if not followers.count %}
<div>{% blocktrans with username=user|username %}{{ username }} has no followers{% endblocktrans %}</div>
<div>{% blocktrans with username=user.display_name %}{{ username }} has no followers{% endblocktrans %}</div>
{% endif %}
</div>
{% endblock %}

View file

@ -14,8 +14,11 @@
{% for follower in user.following.all %}
<div class="block columns">
<div class="column">
<a href="{{ follower.local_path }}">
{% include 'snippets/avatar.html' with user=follower %}
{% include 'snippets/username.html' with user=follower show_full=True %}
{{ follower.display_name }}
</a>
({{ follower.username }})
</div>
<div class="column">
{% include 'snippets/follow_button.html' with user=follower %}

View file

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

View file

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

View file

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

View file

@ -208,6 +208,9 @@ class BaseActivity(TestCase):
# sets the celery task call to the function call
with patch(
'bookwyrm.activitypub.base_activity.set_related_field.delay'):
with patch('bookwyrm.models.status.Status.ignore_activity') \
as discarder:
discarder.return_value = False
update_data.to_model(model=models.Status, instance=status)
self.assertIsNone(status.attachments.first())

View file

@ -42,6 +42,10 @@ class AbstractConnector(TestCase):
return search_result
def parse_search_data(self, 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):
return data['type'] == 'work'
def get_edition_from_work_data(self, data):

View file

@ -18,6 +18,7 @@ class AbstractConnector(TestCase):
books_url='https://example.com/books',
covers_url='https://example.com/covers',
search_url='https://example.com/search?q=',
isbn_search_url='https://example.com/isbn',
)
class TestConnector(abstract_connector.AbstractMinimalConnector):
@ -28,6 +29,10 @@ class AbstractConnector(TestCase):
pass
def parse_search_data(self, 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')
@ -39,6 +44,7 @@ class AbstractConnector(TestCase):
self.assertEqual(connector.books_url, 'https://example.com/books')
self.assertEqual(connector.covers_url, 'https://example.com/covers')
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.assertEqual(connector.identifier, 'example.com')
self.assertIsNone(connector.max_query_count)

View file

@ -27,6 +27,7 @@ class Openlibrary(TestCase):
books_url='https://openlibrary.org',
covers_url='https://covers.openlibrary.org',
search_url='https://openlibrary.org/search?q=',
isbn_search_url='https://openlibrary.org/isbn',
)
self.connector = Connector('openlibrary.org')
@ -149,6 +150,34 @@ class Openlibrary(TestCase):
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
def test_load_edition_data(self):
''' 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()
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
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):

View file

@ -150,7 +150,7 @@ class Status(TestCase):
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
activity['attachment'][0].name, 'Test Edition')
def test_comment_to_activity(self, _):
''' 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' % \
(settings.DOMAIN, self.book.cover.url))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
activity['attachment'][0].name, 'Test Edition')
def test_quotation_to_activity(self, _):
''' 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' % \
(settings.DOMAIN, self.book.cover.url))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
activity['attachment'][0].name, 'Test Edition')
def test_review_to_activity(self, _):
''' 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' % \
(settings.DOMAIN, self.book.cover.url))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
activity['attachment'][0].name, 'Test Edition')
def test_favorite(self, _):
''' fav a status '''

View file

@ -74,7 +74,7 @@ class Inbox(TestCase):
mock_valid.return_value = False
result = self.client.post(
'/user/mouse/inbox',
'{"type": "Test", "object": "exists"}',
'{"type": "Announce", "object": "exists"}',
content_type="application/json"
)
self.assertEqual(result.status_code, 401)
@ -484,7 +484,7 @@ class Inbox(TestCase):
'actor': 'https://example.com/users/rat',
'type': 'Like',
'published': 'Mon, 25 May 2020 19:31:20 GMT',
'object': 'https://example.com/status/1',
'object': self.status.remote_id,
}
views.inbox.activity_task(activity)
@ -494,6 +494,21 @@ class Inbox(TestCase):
self.assertEqual(fav.remote_id, 'https://example.com/fav/1')
self.assertEqual(fav.user, self.remote_user)
def test_ignore_favorite(self):
''' don't try to save an unknown status '''
activity = {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': 'https://example.com/fav/1',
'actor': 'https://example.com/users/rat',
'type': 'Like',
'published': 'Mon, 25 May 2020 19:31:20 GMT',
'object': 'https://unknown.status/not-found',
}
views.inbox.activity_task(activity)
self.assertFalse(models.Favorite.objects.exists())
def test_handle_unfavorite(self):
''' fav a status '''
activity = {

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
def parse_search_data(self, data):
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(
identifier='example.com',
connector_file='openlibrary',

View file

@ -137,6 +137,9 @@ urlpatterns = [
re_path(r'^switch-edition/?$', views.switch_edition),
re_path(r'^create-book/?$', views.EditBook.as_view()),
# isbn
re_path(r'^isbn/(?P<isbn>\d+)(.json)?/?$', views.Isbn.as_view()),
# author
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()),

View file

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

View file

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

View file

@ -20,7 +20,7 @@ class Inbox(View):
''' requests sent by outside servers'''
def post(self, request, username=None):
''' only works as POST request '''
# first let's do some basic checks to see if this is legible
# make sure the user's inbox even exists
if username:
try:
models.User.objects.get(localname=username)
@ -33,6 +33,11 @@ class Inbox(View):
except json.decoder.JSONDecodeError:
return HttpResponseBadRequest()
if not 'object' in activity_json or \
not 'type' in activity_json or \
not activity_json['type'] in activitypub.activity_objects:
return HttpResponseNotFound()
# verify the signature
if not has_valid_signature(request, activity_json):
if activity_json['type'] == 'Delete':
@ -42,12 +47,6 @@ class Inbox(View):
return HttpResponse()
return HttpResponse(status=401)
# just some quick smell tests before we try to parse the json
if not 'object' in activity_json or \
not 'type' in activity_json or \
not activity_json['type'] in activitypub.activity_objects:
return HttpResponseNotFound()
activity_task.delay(activity_json)
return HttpResponse()
@ -63,7 +62,11 @@ def activity_task(activity_json):
# cool that worked, now we should do the action described by the type
# (create, update, delete, etc)
try:
activity.action()
except activitypub.ActivitySerializerError:
# this is raised if the activity is discarded
return
def has_valid_signature(request, activity):

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 ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-02 21:36+0000\n"
"POT-Creation-Date: 2021-03-07 23:40+0000\n"
"PO-Revision-Date: 2021-03-02 17:19-0800\n"
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
"Language-Team: English <LL@li.org>\n"
@ -20,24 +20,24 @@ msgstr ""
#: bookwyrm/forms.py:185
msgid "One Day"
msgstr ""
msgstr "Ein Tag"
#: bookwyrm/forms.py:186
msgid "One Week"
msgstr ""
msgstr "Eine Woche"
#: bookwyrm/forms.py:187
msgid "One Month"
msgstr ""
msgstr "Ein Monat"
#: bookwyrm/forms.py:188
msgid "Does Not Expire"
msgstr ""
msgstr "Läuft nicht aus"
#: bookwyrm/forms.py:190
#, python-format
msgid "%(count)d uses"
msgstr ""
msgstr "%(count)d Benutzungen"
#: bookwyrm/forms.py:192
#, fuzzy
@ -48,38 +48,40 @@ msgstr "Ungelistet"
#: bookwyrm/models/fields.py:24
#, python-format
msgid "%(value)s is not a valid remote_id"
msgstr ""
msgstr "%(value)s ist keine gültige remote_id"
#: bookwyrm/models/fields.py:33 bookwyrm/models/fields.py:42
#, python-format
msgid "%(value)s is not a valid username"
msgstr ""
msgstr "%(value)s ist kein gültiger Username"
#: bookwyrm/models/fields.py:164
#, fuzzy
#| msgid "Server name"
#: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
msgid "username"
msgstr "Servername"
msgstr "Username"
#: bookwyrm/models/fields.py:169
msgid "A user with that username already exists."
msgstr ""
msgstr "Dieser Benutzename ist bereits vergeben."
#: bookwyrm/settings.py:142
msgid "English"
msgstr ""
msgstr "Englisch"
#: bookwyrm/settings.py:143
msgid "German"
msgstr ""
msgstr "Deutsch"
#: bookwyrm/settings.py:144
msgid "French"
msgid "Spanish"
msgstr ""
#: bookwyrm/settings.py:145
msgid "French"
msgstr "Französisch"
#: bookwyrm/settings.py:146
msgid "Simplified Chinese"
msgstr ""
msgstr "Vereinfachtes Chinesisch"
#: bookwyrm/templates/author.html:16 bookwyrm/templates/author.html:17
#: bookwyrm/templates/edit_author.html:5
@ -96,8 +98,10 @@ msgid "Books by %(name)s"
msgstr "Bücher von %(name)s"
#: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by"
msgstr ""
msgstr "von"
#: bookwyrm/templates/book.html:29 bookwyrm/templates/book.html:30
#: bookwyrm/templates/edit_book.html:5
@ -126,15 +130,15 @@ msgstr ""
#: bookwyrm/templates/book.html:84
#, fuzzy, python-format
#| msgid "of %(book.pages)s pages"
#| msgid "%(format)s, %(pages)s pages"
msgid "%(format)s, %(pages)s pages"
msgstr "von %(book.pages)s Seiten"
msgstr "%(format)s, %(book.pages)s Seiten"
#: bookwyrm/templates/book.html:86
#, fuzzy, python-format
#| msgid "of %(book.pages)s pages"
#| msgid "%(pages)s pages"
msgid "%(pages)s pages"
msgstr "von %(book.pages)s Seiten"
msgstr "%(book.pages)s Seiten"
#: bookwyrm/templates/book.html:91
msgid "View on OpenLibrary"
@ -144,8 +148,8 @@ msgstr "In OpenLibrary ansehen"
#, python-format
msgid "(%(review_count)s review)"
msgid_plural "(%(review_count)s reviews)"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "(%(review_count)s Bewertung)"
msgstr[1] "(%(review_count)s Bewertungen)"
#: bookwyrm/templates/book.html:106
msgid "Add Description"
@ -230,7 +234,7 @@ msgstr "Orte"
#: bookwyrm/templates/book.html:229 bookwyrm/templates/layout.html:64
#: bookwyrm/templates/lists/lists.html:4 bookwyrm/templates/lists/lists.html:9
#: bookwyrm/templates/search_results.html:90
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/user/user_layout.html:62
msgid "Lists"
msgstr "Listen"
@ -257,7 +261,7 @@ msgstr ""
#: bookwyrm/templates/discover/about.html:13
#: bookwyrm/templates/discover/about.html:29
msgid "Privacy Policy"
msgstr ""
msgstr "Datenschutzerklärung"
#: bookwyrm/templates/discover/discover.html:6
msgid "Recent Books"
@ -428,7 +432,7 @@ msgid "Direct Messages with <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/layout.html:79
#: bookwyrm/templates/layout.html:87
msgid "Direct Messages"
msgstr "Direktnachrichten"
@ -482,20 +486,20 @@ msgstr "Hier sind noch keine Bücher! Versuche nach Büchern zu suchen um loszul
#, fuzzy
#| msgid "Read"
msgid "To Read"
msgstr "Lesen"
msgstr "Auf der Leseliste"
#: bookwyrm/templates/feed/feed_layout.html:24
#: bookwyrm/templates/user/shelf.html:24
#, fuzzy
#| msgid "Start reading"
msgid "Currently Reading"
msgstr "Zu lesen beginnen"
msgstr "Gerade lesend"
#: bookwyrm/templates/feed/feed_layout.html:25
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11
#: bookwyrm/templates/user/shelf.html:24
msgid "Read"
msgstr "Lesen"
msgstr "Gelesen"
#: bookwyrm/templates/feed/feed_layout.html:76 bookwyrm/templates/goal.html:26
#: bookwyrm/templates/snippets/goal_card.html:6
@ -530,7 +534,7 @@ msgstr "%(name)s hat sich für %(year)s kein Leseziel gesetzt."
#: bookwyrm/templates/goal.html:51
#, python-format
msgid "Your %(year)s Books"
msgstr "Deine %(year)s Bücher"
msgstr "Deine Bücher %(year)s"
#: bookwyrm/templates/goal.html:53
#, python-format
@ -538,7 +542,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "%(username)ss %(year)s Bücher"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94
#: bookwyrm/templates/layout.html:102
msgid "Import Books"
msgstr "Bücher importieren"
@ -595,35 +599,40 @@ msgstr "(Aktualisiere für ein Update!)"
msgid "Failed to load"
msgstr "Laden fehlgeschlagen"
#: bookwyrm/templates/import_status.html:59
#: bookwyrm/templates/import_status.html:44
#, python-format
msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import."
msgstr ""
#: bookwyrm/templates/import_status.html:79
msgid "Select all"
msgstr "Alle auswählen"
#: bookwyrm/templates/import_status.html:62
#: bookwyrm/templates/import_status.html:82
msgid "Retry items"
msgstr "Punkte erneut versuchen"
#: bookwyrm/templates/import_status.html:84
#: bookwyrm/templates/import_status.html:108
msgid "Successfully imported"
msgstr "Erfolgreich importiert"
#: bookwyrm/templates/import_status.html:88
#: bookwyrm/templates/import_status.html:112
#: bookwyrm/templates/lists/curate.html:14
msgid "Book"
msgstr "Buch"
#: bookwyrm/templates/import_status.html:91
#: bookwyrm/templates/import_status.html:115
#: bookwyrm/templates/snippets/create_status_form.html:10
#: bookwyrm/templates/snippets/shelf.html:10
msgid "Title"
msgstr "Titel"
#: bookwyrm/templates/import_status.html:94
#: bookwyrm/templates/import_status.html:118
#: bookwyrm/templates/snippets/shelf.html:11
msgid "Author"
msgstr "Autor*in"
#: bookwyrm/templates/import_status.html:117
#: bookwyrm/templates/import_status.html:141
msgid "Imported"
msgstr "Importiert"
@ -640,6 +649,28 @@ msgstr "Zugiff verweigert"
msgid "Sorry! This invite code is no longer valid."
msgstr "Sorry! Dieser Einladecode ist mehr gültig."
#: bookwyrm/templates/isbn_search_results.html:4
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr "Suchergebnisse"
#: bookwyrm/templates/isbn_search_results.html:9
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "Suchergebnisse für \"%(query)s\""
#: bookwyrm/templates/isbn_search_results.html:14
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "Passende Bücher"
#: bookwyrm/templates/isbn_search_results.html:17
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "Keine Bücher für \"%(query)s\" gefunden"
#: bookwyrm/templates/layout.html:33
msgid "Search for a book or user"
msgstr "Suche nach Buch oder Benutzer*in"
@ -661,55 +692,72 @@ msgstr "Deine Regale"
msgid "Feed"
msgstr ""
#: bookwyrm/templates/layout.html:84
#: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile"
msgstr ""
msgstr "Profil"
#: bookwyrm/templates/layout.html:89
#: bookwyrm/templates/layout.html:97
msgid "Settings"
msgstr "Einstellungen"
#: bookwyrm/templates/layout.html:103
#: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites"
msgstr "Einladungen"
#: bookwyrm/templates/layout.html:110
#: bookwyrm/templates/layout.html:118
msgid "Site Configuration"
msgstr "Seiteneinstellungen"
#: bookwyrm/templates/layout.html:117
#: bookwyrm/templates/layout.html:125
msgid "Log out"
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:10
msgid "Notifications"
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/snippets/register_form.html:4
msgid "Username:"
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
msgid "Log in"
msgstr "Anmelden"
#: bookwyrm/templates/layout.html:183
#: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server"
msgstr "Über diesen Server"
#: bookwyrm/templates/layout.html:187
#: bookwyrm/templates/layout.html:195
msgid "Contact site admin"
msgstr "Admin kontaktieren"
#: bookwyrm/templates/layout.html:198
#: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site_name)s on <a href=\"%(support_link)s\" target=\"_blank\">%(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>."
msgstr "BookWyrm ist open source Software. Du kannst dich auf <a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> beteiligen oder etwas melden."
@ -718,6 +766,18 @@ msgstr "BookWyrm ist open source Software. Du kannst dich auf <a href=\"https://
msgid "Create List"
msgstr "Liste erstellen"
#: bookwyrm/templates/lists/created_text.html:5
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "Created and curated by <a href=\"%(path)s\">%(username)s</a>"
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/lists/created_text.html:7
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "Created by <a href=\"%(path)s\">%(username)s</a>"
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/lists/curate.html:6
msgid "Pending Books"
msgstr "Unbestätigte Bücher"
@ -743,7 +803,7 @@ msgid "Discard"
msgstr "Ablehnen"
#: bookwyrm/templates/lists/edit_form.html:5
#: bookwyrm/templates/lists/list_layout.html:17
#: bookwyrm/templates/lists/list_layout.html:18
msgid "Edit List"
msgstr "Liste bearbeiten"
@ -822,16 +882,6 @@ msgstr "Keine Bücher gefunden"
msgid "Suggest"
msgstr "Vorschlagen"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created and curated by"
msgstr "Erstellt und kuratiert von"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created by"
msgstr "Erstellt von"
#: bookwyrm/templates/lists/lists.html:14
msgid "Your lists"
msgstr "Deine Listen"
@ -855,10 +905,6 @@ msgstr ""
msgid "Password:"
msgstr "Passwort:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Passwort vergessen?"
#: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite"
msgstr "Kontaktiere für eine Einladung eine*n Admin"
@ -872,117 +918,117 @@ msgid "Not Found"
msgstr "Nicht gefunden"
#: 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!"
#: bookwyrm/templates/notifications.html:14
msgid "Delete notifications"
msgstr "Benachrichtigungen löschen"
#: bookwyrm/templates/notifications.html:49
#: bookwyrm/templates/notifications.html:51
#, python-format
msgid "favorited 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> favorisiert"
#: bookwyrm/templates/notifications.html:51
#: bookwyrm/templates/notifications.html:53
#, python-format
msgid "favorited 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> favorisiert"
#: bookwyrm/templates/notifications.html:53
#: bookwyrm/templates/notifications.html:55
#, python-format
msgid "favorited 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>"
msgstr " hat dein <a href=\"%(related_path)s\">Zitat aus <em>%(book_title)s</em></a> favorisiert"
#: bookwyrm/templates/notifications.html:55
#: bookwyrm/templates/notifications.html:57
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">status</a>"
msgstr "hat deinen <a href=\"%(related_path)s\">Status</a> favorisiert"
#: bookwyrm/templates/notifications.html:60
#: bookwyrm/templates/notifications.html:62
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "hat dich in einer <a href=\"%(related_path)s\">Bewertung von <em>%(book_title)s</em></a> erwähnt"
#: bookwyrm/templates/notifications.html:62
#: bookwyrm/templates/notifications.html:64
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr "hat dich in einem <a href=\"%(related_path)s\">Kommentar zu <em>%(book_title)s</em></a> erwähnt"
#: bookwyrm/templates/notifications.html:64
#: bookwyrm/templates/notifications.html:66
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "hat dich in einem <a href=\"%(related_path)s\">Zitat von <em>%(book_title)s</em></a> erwähnt"
#: bookwyrm/templates/notifications.html:66
#: bookwyrm/templates/notifications.html:68
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">status</a>"
msgstr "hat dich in einem <a href=\"%(related_path)s\">Status</a> erwähnt"
#: bookwyrm/templates/notifications.html:71
#: bookwyrm/templates/notifications.html:73
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">review of <em>%(book_title)s</em></a>"
msgstr "hat auf deine <a href=\"%(parent_path)s\">Bewertung von <em>%(book_title)s</em></a> <a href=\"%(related_path)s\">geantwortet</a> "
#: bookwyrm/templates/notifications.html:73
#: bookwyrm/templates/notifications.html:75
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr "hat auf deinen <a href=\"%(parent_path)s\">Kommentar zu <em>%(book_title)s</em></a> <a href=\"%(related_path)s\">geantwortet</a>"
#: bookwyrm/templates/notifications.html:75
#: bookwyrm/templates/notifications.html:77
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr "hat auf dein <a href=\"%(parent_path)s\">Zitat aus <em>%(book_title)s</em></a> <a href=\"%(related_path)s\">geantwortet</a>"
#: bookwyrm/templates/notifications.html:77
#: bookwyrm/templates/notifications.html:79
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgstr "hat auf deinen <a href=\"%(parent_path)s\">Status</a> <a href=\"%(related_path)s\">geantwortet</a>"
#: bookwyrm/templates/notifications.html:81
#: bookwyrm/templates/notifications.html:83
msgid "followed you"
msgstr "folgt dir"
#: bookwyrm/templates/notifications.html:84
#: bookwyrm/templates/notifications.html:86
msgid "sent you a follow request"
msgstr "hat dir eine Folgeanfrage geschickt"
#: bookwyrm/templates/notifications.html:90
#, python-format
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"
#: bookwyrm/templates/notifications.html:92
#, python-format
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"
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"
#: bookwyrm/templates/notifications.html:94
#, python-format
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"
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"
#: bookwyrm/templates/notifications.html:96
#, python-format
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"
#: bookwyrm/templates/notifications.html:98
#, python-format
msgid "boosted your <a href=\"%(related_path)s\">status</a>"
msgstr "hat deinen <a href=\"%(related_path)s\">Status</a> geteilt"
#: bookwyrm/templates/notifications.html:100
#: bookwyrm/templates/notifications.html:102
#, python-format
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 "hat <em><a href=\"%(book_path)s\">%(book_title)s</a></em> zu deiner Liste \"<a href=\"%(list_path)s\">%(list_name)s</a>\" Hinzugefügt"
#: bookwyrm/templates/notifications.html:102
#: bookwyrm/templates/notifications.html:104
#, python-format
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 "hat <em><a href=\"%(book_path)s\">%(book_title)s</a></em> für deine Liste \"<a href=\"%(list_path)s/curate\">%(list_name)s</a>\" vorgeschlagen"
#: bookwyrm/templates/notifications.html:106
#: bookwyrm/templates/notifications.html:108
#, python-format
msgid " your <a href=\"/import/%(related_id)s\">import</a> completed."
msgstr " dein <a href=\"/import/%(related_id)s\">Import</a> ist abgeschlossen."
#: bookwyrm/templates/notifications.html:138
#: bookwyrm/templates/notifications.html:142
msgid "You're all caught up!"
msgstr "Du bist auf dem neusten Stand!"
@ -1052,7 +1098,7 @@ msgstr "Displayname:"
#: bookwyrm/templates/preferences/edit_user.html:31
msgid "Summary:"
msgstr "Zusammenfassung:"
msgstr "Bio:"
#: bookwyrm/templates/preferences/edit_user.html:46
msgid "Manually approve followers:"
@ -1066,24 +1112,6 @@ msgstr ""
msgid "Relationships"
msgstr "Beziehungen"
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr "Suchergebnisse"
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "Suchergebnisse für \"%(query)s\""
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "Passende Bücher"
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "Keine Bücher für \"%(query)s\" gefunden"
#: bookwyrm/templates/search_results.html:33
msgid "Didn't find what you were looking for?"
msgstr "Nicht gefunden, wonach du gesucht hast?"
@ -1109,7 +1137,7 @@ msgstr "Passende Nutzer*innen"
msgid "No users found for \"%(query)s\""
msgstr "Keine Nutzer*innen für \"%(query)s\" gefunden"
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/search_results.html:94
#, python-format
msgid "No lists found for \"%(query)s\""
msgstr "Keine Liste für \"%(query)s\" gefunden"
@ -1268,7 +1296,7 @@ msgstr ""
#: bookwyrm/templates/snippets/book_titleby.html:3
#, python-format
msgid "<a href=\"%(path)s\">%(title)s</a> by "
msgstr "<a href=\"%(path)s\">%(title)s</a> von"
msgstr "<a href=\"%(path)s\">%(title)s</a> von "
#: bookwyrm/templates/snippets/boost_button.html:8
#: bookwyrm/templates/snippets/boost_button.html:9
@ -1312,7 +1340,7 @@ msgstr ""
#: bookwyrm/templates/snippets/rate_action.html:14
#: bookwyrm/templates/snippets/stars.html:3
msgid "No rating"
msgstr ""
msgstr "Kein Rating"
#: bookwyrm/templates/snippets/create_status_form.html:54
msgid "Include spoiler alert"
@ -1327,7 +1355,7 @@ msgstr "Privat"
#: bookwyrm/templates/snippets/create_status_form.html:67
msgid "Post"
msgstr ""
msgstr "Absenden"
#: bookwyrm/templates/snippets/delete_readthrough_modal.html:4
msgid "Delete these read dates?"
@ -1435,11 +1463,11 @@ msgstr "%(username)s hat <a href=\"%(path)s\">%(read_count)s von %(goal_count)s
#: bookwyrm/templates/snippets/pagination.html:7
msgid "Previous"
msgstr "Vorher"
msgstr "Zurück"
#: bookwyrm/templates/snippets/pagination.html:15
msgid "Next"
msgstr "Danach"
msgstr "Weiter"
#: bookwyrm/templates/snippets/privacy-icons.html:3
#: bookwyrm/templates/snippets/privacy-icons.html:4
@ -1499,7 +1527,7 @@ msgstr "Fortschrittsupdates:"
#: bookwyrm/templates/snippets/readthrough.html:11
msgid "finished"
msgstr "beendet"
msgstr "Abgeschlossen"
#: bookwyrm/templates/snippets/readthrough.html:14
msgid "Show all updates"
@ -1535,31 +1563,31 @@ msgstr "Fortschritt"
#: bookwyrm/templates/snippets/readthrough_form.html:30
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25
msgid "Finished reading"
msgstr "Lesen beendet"
msgstr "Lesen abgeschlossen"
#: bookwyrm/templates/snippets/register_form.html:32
msgid "Sign Up"
msgstr "Registrieren"
#: bookwyrm/templates/snippets/rss_title.html:5
#: bookwyrm/templates/snippets/status/status_header.html:9
#: bookwyrm/templates/snippets/status/status_header.html:11
msgid "rated"
msgstr ""
#: bookwyrm/templates/snippets/rss_title.html:7
#: bookwyrm/templates/snippets/status/status_header.html:11
#: bookwyrm/templates/snippets/status/status_header.html:13
msgid "reviewed"
msgstr "bewertet"
msgstr "bewertete"
#: bookwyrm/templates/snippets/rss_title.html:9
#: bookwyrm/templates/snippets/status/status_header.html:13
#: bookwyrm/templates/snippets/status/status_header.html:15
msgid "commented on"
msgstr "kommentiert zu"
msgstr "kommentierte"
#: bookwyrm/templates/snippets/rss_title.html:11
#: bookwyrm/templates/snippets/status/status_header.html:15
#: bookwyrm/templates/snippets/status/status_header.html:17
msgid "quoted"
msgstr "zitiert"
msgstr "zitierte"
#: bookwyrm/templates/snippets/search_result_text.html:3
#, python-format
@ -1580,7 +1608,7 @@ msgstr "Gestartet"
#: bookwyrm/templates/snippets/shelf.html:15
msgid "Finished"
msgstr "Beendet"
msgstr "Abgeschlossen"
#: bookwyrm/templates/snippets/shelf.html:16
msgid "External links"
@ -1609,7 +1637,7 @@ msgstr "Vom Regal nehmen"
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5
#, python-format
msgid "Finish \"<em>%(book_title)s</em>\""
msgstr "\"<em>%(book_title)s</em>\" beenden"
msgstr "\"<em>%(book_title)s</em>\" abschließen"
#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5
msgid "More shelves"
@ -1621,7 +1649,7 @@ msgstr "Zu lesen beginnen"
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13
msgid "Finish reading"
msgstr "Lesen beenden"
msgstr "Lesen abschließen"
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16
#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26
@ -1638,9 +1666,9 @@ msgstr "\"<em>%(book_title)s</em>\" beginnen"
msgid "Want to Read \"<em>%(book_title)s</em>\""
msgstr "\"<em>%(book_title)s</em>\" auf Leseliste setzen"
#: bookwyrm/templates/snippets/status/status.html:7
#: bookwyrm/templates/snippets/status/status.html:9
msgid "boosted"
msgstr "geteilt"
msgstr "teilt"
#: bookwyrm/templates/snippets/status/status_body.html:24
#: bookwyrm/templates/snippets/status/status_body.html:37
@ -1648,28 +1676,50 @@ msgstr "geteilt"
msgid "Reply"
msgstr "Antwort"
#: bookwyrm/templates/snippets/status/status_content.html:16
#: bookwyrm/templates/snippets/trimmed_text.html:12
#: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more"
msgstr "Mehr anzeigen"
#: bookwyrm/templates/snippets/status/status_content.html:23
#: bookwyrm/templates/snippets/trimmed_text.html:18
#: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less"
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"
msgstr "Bild in neuem Fenster öffnen"
#: bookwyrm/templates/snippets/status/status_header.html:22
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">review</a>"
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/snippets/status/status_header.html:24
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">comment</a>"
msgstr "hat auf deinen <a href=\"%(parent_path)s\">Status</a> geantwortet</a>"
#: bookwyrm/templates/snippets/status/status_header.html:26
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">quote</a>"
msgstr "hat auf deinen <a href=\"%(parent_path)s\">Status</a> <a href=\"%(related_path)s\">geantwortet</a>"
#: bookwyrm/templates/snippets/status/status_header.html:28
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">status</a>"
msgstr "hat auf deinen <a href=\"%(parent_path)s\">Status</a> <a href=\"%(related_path)s\">geantwortet</a>"
#: bookwyrm/templates/snippets/status/status_options.html:7
#: bookwyrm/templates/snippets/user_options.html:7
msgid "More options"
msgstr "Mehr Optionen"
#: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status"
msgstr "Post löschen"
@ -1693,8 +1743,6 @@ msgstr "Mit \"%(tag.name)s\" markierte Bücher"
#: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf"
msgstr "Regal erstellen"
@ -1711,7 +1759,7 @@ msgstr "Regal aktualisieren"
msgid "User Profile"
msgstr "Benutzerprofil"
#: bookwyrm/templates/user/followers.html:26
#: bookwyrm/templates/user/followers.html:29
#, python-format
msgid "%(username)s has no followers"
msgstr "niemand folgt %(username)s "
@ -1720,7 +1768,7 @@ msgstr "niemand folgt %(username)s "
msgid "Following"
msgstr "Folgend"
#: bookwyrm/templates/user/following.html:26
#: bookwyrm/templates/user/following.html:29
#, python-format
msgid "%(username)s isn't following any users"
msgstr "%(username)s folgt niemandem"
@ -1818,7 +1866,13 @@ msgstr[1] "%(counter)s Folgende"
#: bookwyrm/templates/user/user_preview.html:16
#, python-format
msgid "%(counter)s following"
msgstr "%(counter)s folgen"
msgstr "Folgt %(counter)s"
#~ msgid "Created and curated by"
#~ msgstr "Erstellt und kuratiert von"
#~ msgid "Created by"
#~ msgstr "Erstellt von"
#~ msgid "Added by"
#~ msgstr "Hinzugefügt von"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-02 21:36+0000\n"
"POT-Creation-Date: 2021-03-07 23:40+0000\n"
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
"Language-Team: English <LL@li.org>\n"
@ -53,7 +53,7 @@ msgstr ""
msgid "%(value)s is not a valid username"
msgstr ""
#: bookwyrm/models/fields.py:164
#: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
msgid "username"
msgstr ""
@ -70,10 +70,14 @@ msgid "German"
msgstr ""
#: bookwyrm/settings.py:144
msgid "French"
msgid "Spanish"
msgstr ""
#: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese"
msgstr ""
@ -92,6 +96,8 @@ msgid "Books by %(name)s"
msgstr ""
#: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by"
msgstr ""
@ -221,7 +227,7 @@ msgstr ""
#: bookwyrm/templates/book.html:229 bookwyrm/templates/layout.html:64
#: bookwyrm/templates/lists/lists.html:4 bookwyrm/templates/lists/lists.html:9
#: bookwyrm/templates/search_results.html:90
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/user/user_layout.html:62
msgid "Lists"
msgstr ""
@ -419,7 +425,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr ""
#: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79
#: bookwyrm/templates/layout.html:87
msgid "Direct Messages"
msgstr ""
@ -525,7 +531,7 @@ msgid "%(username)s's %(year)s Books"
msgstr ""
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94
#: bookwyrm/templates/layout.html:102
msgid "Import Books"
msgstr ""
@ -582,35 +588,40 @@ msgstr ""
msgid "Failed to load"
msgstr ""
#: bookwyrm/templates/import_status.html:59
#: bookwyrm/templates/import_status.html:44
#, python-format
msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import."
msgstr ""
#: bookwyrm/templates/import_status.html:79
msgid "Select all"
msgstr ""
#: bookwyrm/templates/import_status.html:62
#: bookwyrm/templates/import_status.html:82
msgid "Retry items"
msgstr ""
#: bookwyrm/templates/import_status.html:84
#: bookwyrm/templates/import_status.html:108
msgid "Successfully imported"
msgstr ""
#: bookwyrm/templates/import_status.html:88
#: bookwyrm/templates/import_status.html:112
#: bookwyrm/templates/lists/curate.html:14
msgid "Book"
msgstr ""
#: bookwyrm/templates/import_status.html:91
#: bookwyrm/templates/import_status.html:115
#: bookwyrm/templates/snippets/create_status_form.html:10
#: bookwyrm/templates/snippets/shelf.html:10
msgid "Title"
msgstr ""
#: bookwyrm/templates/import_status.html:94
#: bookwyrm/templates/import_status.html:118
#: bookwyrm/templates/snippets/shelf.html:11
msgid "Author"
msgstr ""
#: bookwyrm/templates/import_status.html:117
#: bookwyrm/templates/import_status.html:141
msgid "Imported"
msgstr ""
@ -627,6 +638,28 @@ msgstr ""
msgid "Sorry! This invite code is no longer valid."
msgstr ""
#: bookwyrm/templates/isbn_search_results.html:4
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr ""
#: bookwyrm/templates/isbn_search_results.html:9
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr ""
#: bookwyrm/templates/isbn_search_results.html:14
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr ""
#: bookwyrm/templates/isbn_search_results.html:17
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr ""
#: bookwyrm/templates/layout.html:33
msgid "Search for a book or user"
msgstr ""
@ -648,55 +681,72 @@ msgstr ""
msgid "Feed"
msgstr ""
#: bookwyrm/templates/layout.html:84
#: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile"
msgstr ""
#: bookwyrm/templates/layout.html:89
#: bookwyrm/templates/layout.html:97
msgid "Settings"
msgstr ""
#: bookwyrm/templates/layout.html:103
#: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites"
msgstr ""
#: bookwyrm/templates/layout.html:110
#: bookwyrm/templates/layout.html:118
msgid "Site Configuration"
msgstr ""
#: bookwyrm/templates/layout.html:117
#: bookwyrm/templates/layout.html:125
msgid "Log out"
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:10
msgid "Notifications"
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/snippets/register_form.html:4
msgid "Username:"
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
msgid "Log in"
msgstr ""
#: bookwyrm/templates/layout.html:183
#: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server"
msgstr ""
#: bookwyrm/templates/layout.html:187
#: bookwyrm/templates/layout.html:195
msgid "Contact site admin"
msgstr ""
#: bookwyrm/templates/layout.html:198
#: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site_name)s on <a href=\"%(support_link)s\" target=\"_blank\">%(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>."
msgstr ""
@ -705,6 +755,16 @@ msgstr ""
msgid "Create List"
msgstr ""
#: bookwyrm/templates/lists/created_text.html:5
#, python-format
msgid "Created and curated by <a href=\"%(path)s\">%(username)s</a>"
msgstr ""
#: bookwyrm/templates/lists/created_text.html:7
#, python-format
msgid "Created by <a href=\"%(path)s\">%(username)s</a>"
msgstr ""
#: bookwyrm/templates/lists/curate.html:6
msgid "Pending Books"
msgstr ""
@ -730,7 +790,7 @@ msgid "Discard"
msgstr ""
#: bookwyrm/templates/lists/edit_form.html:5
#: bookwyrm/templates/lists/list_layout.html:17
#: bookwyrm/templates/lists/list_layout.html:18
msgid "Edit List"
msgstr ""
@ -808,16 +868,6 @@ msgstr ""
msgid "Suggest"
msgstr ""
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created and curated by"
msgstr ""
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created by"
msgstr ""
#: bookwyrm/templates/lists/lists.html:14
msgid "Your lists"
msgstr ""
@ -840,10 +890,6 @@ msgstr ""
msgid "Password:"
msgstr ""
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr ""
#: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite"
msgstr ""
@ -857,117 +903,117 @@ msgid "Not Found"
msgstr ""
#: 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 ""
#: bookwyrm/templates/notifications.html:14
msgid "Delete notifications"
msgstr ""
#: bookwyrm/templates/notifications.html:49
#: bookwyrm/templates/notifications.html:51
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:51
#: bookwyrm/templates/notifications.html:53
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:53
#: bookwyrm/templates/notifications.html:55
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:55
#: bookwyrm/templates/notifications.html:57
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">status</a>"
msgstr ""
#: bookwyrm/templates/notifications.html:60
#: bookwyrm/templates/notifications.html:62
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">review of <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:62
#: bookwyrm/templates/notifications.html:64
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:64
#: bookwyrm/templates/notifications.html:66
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:66
#: bookwyrm/templates/notifications.html:68
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">status</a>"
msgstr ""
#: bookwyrm/templates/notifications.html:71
#: bookwyrm/templates/notifications.html:73
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">review of <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:73
#: bookwyrm/templates/notifications.html:75
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">comment on <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:75
#: bookwyrm/templates/notifications.html:77
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:77
#: bookwyrm/templates/notifications.html:79
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgstr ""
#: bookwyrm/templates/notifications.html:81
#: bookwyrm/templates/notifications.html:83
msgid "followed you"
msgstr ""
#: bookwyrm/templates/notifications.html:84
#: bookwyrm/templates/notifications.html:86
msgid "sent you a follow request"
msgstr ""
#: bookwyrm/templates/notifications.html:90
#, python-format
msgid "boosted your <a href=\"%(related_path)s\">review of <em>%(book.title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:92
#, 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\">review of <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:94
#, 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\">comment on<em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:96
#, python-format
msgid "boosted your <a href=\"%(related_path)s\">status</a>"
msgid "boosted your <a href=\"%(related_path)s\">quote from <em>%(book_title)s</em></a>"
msgstr ""
#: bookwyrm/templates/notifications.html:100
#: bookwyrm/templates/notifications.html:98
#, python-format
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 "boosted your <a href=\"%(related_path)s\">status</a>"
msgstr ""
#: bookwyrm/templates/notifications.html:102
#, python-format
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 ""
#: bookwyrm/templates/notifications.html:104
#, python-format
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 ""
#: bookwyrm/templates/notifications.html:106
#: bookwyrm/templates/notifications.html:108
#, python-format
msgid " your <a href=\"/import/%(related_id)s\">import</a> completed."
msgstr ""
#: bookwyrm/templates/notifications.html:138
#: bookwyrm/templates/notifications.html:142
msgid "You're all caught up!"
msgstr ""
@ -1051,24 +1097,6 @@ msgstr ""
msgid "Relationships"
msgstr ""
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr ""
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr ""
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr ""
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr ""
#: bookwyrm/templates/search_results.html:33
msgid "Didn't find what you were looking for?"
msgstr ""
@ -1094,7 +1122,7 @@ msgstr ""
msgid "No users found for \"%(query)s\""
msgstr ""
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/search_results.html:94
#, python-format
msgid "No lists found for \"%(query)s\""
msgstr ""
@ -1527,22 +1555,22 @@ msgid "Sign Up"
msgstr ""
#: bookwyrm/templates/snippets/rss_title.html:5
#: bookwyrm/templates/snippets/status/status_header.html:9
#: bookwyrm/templates/snippets/status/status_header.html:11
msgid "rated"
msgstr ""
#: bookwyrm/templates/snippets/rss_title.html:7
#: bookwyrm/templates/snippets/status/status_header.html:11
#: bookwyrm/templates/snippets/status/status_header.html:13
msgid "reviewed"
msgstr ""
#: bookwyrm/templates/snippets/rss_title.html:9
#: bookwyrm/templates/snippets/status/status_header.html:13
#: bookwyrm/templates/snippets/status/status_header.html:15
msgid "commented on"
msgstr ""
#: bookwyrm/templates/snippets/rss_title.html:11
#: bookwyrm/templates/snippets/status/status_header.html:15
#: bookwyrm/templates/snippets/status/status_header.html:17
msgid "quoted"
msgstr ""
@ -1623,7 +1651,7 @@ msgstr ""
msgid "Want to Read \"<em>%(book_title)s</em>\""
msgstr ""
#: bookwyrm/templates/snippets/status/status.html:7
#: bookwyrm/templates/snippets/status/status.html:9
msgid "boosted"
msgstr ""
@ -1633,20 +1661,40 @@ msgstr ""
msgid "Reply"
msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:16
#: bookwyrm/templates/snippets/trimmed_text.html:12
#: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more"
msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:23
#: bookwyrm/templates/snippets/trimmed_text.html:18
#: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less"
msgstr ""
#: bookwyrm/templates/snippets/status/status_content.html:44
#: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window"
msgstr ""
#: bookwyrm/templates/snippets/status/status_header.html:22
#, python-format
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">review</a>"
msgstr ""
#: bookwyrm/templates/snippets/status/status_header.html:24
#, python-format
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">comment</a>"
msgstr ""
#: bookwyrm/templates/snippets/status/status_header.html:26
#, python-format
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">quote</a>"
msgstr ""
#: bookwyrm/templates/snippets/status/status_header.html:28
#, python-format
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">status</a>"
msgstr ""
#: bookwyrm/templates/snippets/status/status_options.html:7
#: bookwyrm/templates/snippets/user_options.html:7
msgid "More options"
@ -1692,7 +1740,7 @@ msgstr ""
msgid "User Profile"
msgstr ""
#: bookwyrm/templates/user/followers.html:26
#: bookwyrm/templates/user/followers.html:29
#, python-format
msgid "%(username)s has no followers"
msgstr ""
@ -1701,7 +1749,7 @@ msgstr ""
msgid "Following"
msgstr ""
#: bookwyrm/templates/user/following.html:26
#: bookwyrm/templates/user/following.html:29
#, python-format
msgid "%(username)s isn't following any users"
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 ""
"Project-Id-Version: 0.1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-02 21:36+0000\n"
"POT-Creation-Date: 2021-03-07 23:40+0000\n"
"PO-Revision-Date: 2021-03-02 12:37+0100\n"
"Last-Translator: Fabien Basmaison <contact@arkhi.org>\n"
"Language-Team: Mouse Reeve <LL@li.org>\n"
@ -55,7 +55,7 @@ msgstr ""
msgid "%(value)s is not a valid username"
msgstr ""
#: bookwyrm/models/fields.py:164
#: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
#, fuzzy
#| msgid "Username:"
msgid "username"
@ -74,10 +74,14 @@ msgid "German"
msgstr ""
#: bookwyrm/settings.py:144
msgid "French"
msgid "Spanish"
msgstr ""
#: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese"
msgstr ""
@ -96,6 +100,8 @@ msgid "Books by %(name)s"
msgstr "Livres par %(name)s"
#: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by"
msgstr ""
@ -234,7 +240,7 @@ msgstr "Lieux"
#: bookwyrm/templates/book.html:229 bookwyrm/templates/layout.html:64
#: bookwyrm/templates/lists/lists.html:4 bookwyrm/templates/lists/lists.html:9
#: bookwyrm/templates/search_results.html:90
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/user/user_layout.html:62
msgid "Lists"
msgstr "Listes"
@ -431,15 +437,12 @@ msgid "Something went wrong! Sorry about that."
msgstr "Une erreur sest produite; désolé!"
#: bookwyrm/templates/feed/direct_messages.html:8
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#, python-format
msgid "Direct Messages with <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/layout.html:79
#, fuzzy
#| msgid "Send direct message"
#: bookwyrm/templates/layout.html:87
msgid "Direct Messages"
msgstr "Messages directs"
@ -555,7 +558,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "Livres de %(username)s en %(year)s"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94
#: bookwyrm/templates/layout.html:102
msgid "Import Books"
msgstr "Importer des livres"
@ -610,37 +613,42 @@ msgstr "(Rechargez la page pour mettre à jour!"
#: bookwyrm/templates/import_status.html:35
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:44
#, 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:79
msgid "Select all"
msgstr "Tout sélectionner"
#: bookwyrm/templates/import_status.html:62
#: bookwyrm/templates/import_status.html:82
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:108
msgid "Successfully imported"
msgstr "Importation réussie"
#: bookwyrm/templates/import_status.html:88
#: bookwyrm/templates/import_status.html:112
#: bookwyrm/templates/lists/curate.html:14
msgid "Book"
msgstr "Livre"
#: bookwyrm/templates/import_status.html:91
#: bookwyrm/templates/import_status.html:115
#: bookwyrm/templates/snippets/create_status_form.html:10
#: bookwyrm/templates/snippets/shelf.html:10
msgid "Title"
msgstr "Titre"
#: bookwyrm/templates/import_status.html:94
#: bookwyrm/templates/import_status.html:118
#: bookwyrm/templates/snippets/shelf.html:11
msgid "Author"
msgstr "Auteur ou autrice"
#: bookwyrm/templates/import_status.html:117
#: bookwyrm/templates/import_status.html:141
msgid "Imported"
msgstr "Importé"
@ -657,9 +665,29 @@ msgstr "Autorisation refusée"
msgid "Sorry! This invite code is no longer valid."
msgstr "Cette invitation nest plus valide; désolé!"
#: bookwyrm/templates/isbn_search_results.html:4
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr "Résultats de recherche"
#: bookwyrm/templates/isbn_search_results.html:9
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "Résultats de recherche pour « %(query)s»"
#: bookwyrm/templates/isbn_search_results.html:14
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "Livres correspondants"
#: bookwyrm/templates/isbn_search_results.html:17
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "Aucun livre trouvé pour « %(query)s»"
#: bookwyrm/templates/layout.html:33
#, fuzzy
#| msgid "Search for a book"
msgid "Search for a book or user"
msgstr "Chercher un livre ou un compte"
@ -680,59 +708,76 @@ msgstr "Vos étagères"
msgid "Feed"
msgstr "Fil dactualité"
#: bookwyrm/templates/layout.html:84
#: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile"
msgstr "Profil"
#: bookwyrm/templates/layout.html:89
#: bookwyrm/templates/layout.html:97
#, fuzzy
#| msgid "Instance Settings"
msgid "Settings"
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/manage_invites.html:3
msgid "Invites"
msgstr "Invitations"
#: bookwyrm/templates/layout.html:110
#: bookwyrm/templates/layout.html:118
msgid "Site Configuration"
msgstr "Configuration du site"
#: bookwyrm/templates/layout.html:117
#, fuzzy
#| msgid "Log in"
#: bookwyrm/templates/layout.html:125
msgid "Log out"
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:10
msgid "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/snippets/register_form.html:4
msgid "Username:"
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
msgid "Log in"
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"
msgstr "À propos de ce serveur"
#: bookwyrm/templates/layout.html:187
#: bookwyrm/templates/layout.html:195
msgid "Contact site admin"
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=\"%(support_link)s\" target=\"_blank\">%(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>."
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>."
@ -741,6 +786,18 @@ msgstr "Bookwyrm est un logiciel libre. Vous pouvez contribuer ou faire des rapp
msgid "Create List"
msgstr "Créer une liste"
#: bookwyrm/templates/lists/created_text.html:5
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "Created and curated by <a href=\"%(path)s\">%(username)s</a>"
msgstr "Messages directs avec <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/lists/created_text.html:7
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "Created by <a href=\"%(path)s\">%(username)s</a>"
msgstr "Messages directs avec <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/lists/curate.html:6
msgid "Pending Books"
msgstr "Livres en attente de modération"
@ -766,7 +823,7 @@ msgid "Discard"
msgstr "Rejeter"
#: bookwyrm/templates/lists/edit_form.html:5
#: bookwyrm/templates/lists/list_layout.html:17
#: bookwyrm/templates/lists/list_layout.html:18
msgid "Edit List"
msgstr "Modifier la liste"
@ -845,16 +902,6 @@ msgstr "Aucun livre trouvé"
msgid "Suggest"
msgstr "Suggérer"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created and curated by"
msgstr "Créée et modérée par"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created by"
msgstr "Créée par"
#: bookwyrm/templates/lists/lists.html:14
msgid "Your lists"
msgstr "Vos listes"
@ -878,10 +925,6 @@ msgstr "Connexion"
msgid "Password:"
msgstr "Mot de passe:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "Mot de passe oublié?"
#: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite"
msgstr "Contacter un administrateur pour obtenir une invitation"
@ -895,135 +938,117 @@ msgid "Not Found"
msgstr "Introuvable"
#: 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!"
#: bookwyrm/templates/notifications.html:14
msgid "Delete notifications"
msgstr "Supprimer les notifications"
#: bookwyrm/templates/notifications.html:49
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:51
#, python-format
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"
#: bookwyrm/templates/notifications.html:51
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:53
#, python-format
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"
#: bookwyrm/templates/notifications.html:53
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:55
#, python-format
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"
#: bookwyrm/templates/notifications.html:55
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:57
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">status</a>"
msgstr "a ajouté votre <a href=\"%(related_path)s\">statut</a> à ses favoris"
#: bookwyrm/templates/notifications.html:60
#, fuzzy, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:62
#, python-format
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>"
#: bookwyrm/templates/notifications.html:62
#, fuzzy, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:64
#, python-format
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>"
#: bookwyrm/templates/notifications.html:64
#, fuzzy, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:66
#, python-format
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>"
#: bookwyrm/templates/notifications.html:66
#, fuzzy, python-format
#| msgid "mentioned you in a <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:68
#, python-format
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>"
#: bookwyrm/templates/notifications.html:71
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:73
#, python-format
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>"
#: bookwyrm/templates/notifications.html:73
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:75
#, python-format
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>"
#: bookwyrm/templates/notifications.html:75
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:77
#, python-format
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>"
#: bookwyrm/templates/notifications.html:77
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:79
#, python-format
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>"
#: bookwyrm/templates/notifications.html:81
#: bookwyrm/templates/notifications.html:83
msgid "followed you"
msgstr "sest abonné(e)"
#: bookwyrm/templates/notifications.html:84
#: bookwyrm/templates/notifications.html:86
msgid "sent you a follow request"
msgstr "vous a envoyé une demande dabonnement"
#: bookwyrm/templates/notifications.html:90
#, fuzzy, 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>"
#: bookwyrm/templates/notifications.html:92
#, python-format
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>"
#: bookwyrm/templates/notifications.html:92
#, fuzzy, 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>"
#: bookwyrm/templates/notifications.html:94
#, python-format
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>"
#: bookwyrm/templates/notifications.html:94
#, fuzzy, 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>"
#: bookwyrm/templates/notifications.html:96
#, python-format
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>"
#: bookwyrm/templates/notifications.html:96
#, fuzzy, python-format
#| msgid "boosted your <a href=\"%(related_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:98
#, python-format
msgid "boosted your <a href=\"%(related_path)s\">status</a>"
msgstr "a partagé votre <a href=\"%(related_path)s\">statut</a>"
#: bookwyrm/templates/notifications.html:100
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:102
#, python-format
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> »"
#: bookwyrm/templates/notifications.html:102
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">%(preview_name)s</a>"
#: bookwyrm/templates/notifications.html:104
#, python-format
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> »"
#: bookwyrm/templates/notifications.html:106
#: bookwyrm/templates/notifications.html:108
#, python-format
msgid " your <a href=\"/import/%(related_id)s\">import</a> completed."
msgstr " votre <a href=\"/import/%(related_id)s\">importation</a> est terminée."
#: bookwyrm/templates/notifications.html:138
#: bookwyrm/templates/notifications.html:142
msgid "You're all caught up!"
msgstr "Aucune nouvelle notification!"
@ -1107,26 +1132,6 @@ msgstr "Compte"
msgid "Relationships"
msgstr "Relations"
#: bookwyrm/templates/search_results.html:4
#, fuzzy
#| msgid "Search Results for \"%(query)s\""
msgid "Search Results"
msgstr "Résultats de recherche"
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "Résultats de recherche pour « %(query)s»"
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "Livres correspondants"
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "Aucun livre trouvé pour « %(query)s»"
#: bookwyrm/templates/search_results.html:33
msgid "Didn't find what you were looking for?"
msgstr "Vous navez pas trouvé ce que vous cherchiez?"
@ -1152,14 +1157,12 @@ msgstr "Comptes correspondants"
msgid "No users found for \"%(query)s\""
msgstr "Aucun compte trouvé pour « %(query)s»"
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/search_results.html:94
#, python-format
msgid "No lists found for \"%(query)s\""
msgstr "Aucune liste trouvée pour « %(query)s»"
#: bookwyrm/templates/settings/admin_layout.html:4
#, fuzzy
#| msgid "Registration"
msgid "Administration"
msgstr "Administration"
@ -1313,8 +1316,7 @@ msgid "Un-block"
msgstr "Débloquer"
#: bookwyrm/templates/snippets/book_titleby.html:3
#, fuzzy, python-format
#| msgid "Editions of <a href=\"%(work_path)s\">\"%(work_title)s\"</a>"
#, python-format
msgid "<a href=\"%(path)s\">%(title)s</a> by "
msgstr "<a href=\"%(path)s\">%(title)s</a> par "
@ -1363,8 +1365,6 @@ msgid "No rating"
msgstr "Aucune note"
#: bookwyrm/templates/snippets/create_status_form.html:54
#, fuzzy
#| msgid "Spoiler alert:"
msgid "Include spoiler alert"
msgstr "Afficher une alerte spoiler"
@ -1594,22 +1594,22 @@ msgid "Sign Up"
msgstr "Senregistrer"
#: bookwyrm/templates/snippets/rss_title.html:5
#: bookwyrm/templates/snippets/status/status_header.html:9
#: bookwyrm/templates/snippets/status/status_header.html:11
msgid "rated"
msgstr "a noté"
#: bookwyrm/templates/snippets/rss_title.html:7
#: bookwyrm/templates/snippets/status/status_header.html:11
#: bookwyrm/templates/snippets/status/status_header.html:13
msgid "reviewed"
msgstr "a écrit une critique de"
#: bookwyrm/templates/snippets/rss_title.html:9
#: bookwyrm/templates/snippets/status/status_header.html:13
#: bookwyrm/templates/snippets/status/status_header.html:15
msgid "commented on"
msgstr "a commenté"
#: bookwyrm/templates/snippets/rss_title.html:11
#: bookwyrm/templates/snippets/status/status_header.html:15
#: bookwyrm/templates/snippets/status/status_header.html:17
msgid "quoted"
msgstr "a cité"
@ -1694,7 +1694,7 @@ msgstr "Commencer « <em>%(book_title)s</em> »"
msgid "Want to Read \"<em>%(book_title)s</em>\""
msgstr "A envie de lire « <em>%(book_title)s</em> »"
#: bookwyrm/templates/snippets/status/status.html:7
#: bookwyrm/templates/snippets/status/status.html:9
msgid "boosted"
msgstr "partagé"
@ -1704,28 +1704,50 @@ msgstr "partagé"
msgid "Reply"
msgstr "Répondre"
#: bookwyrm/templates/snippets/status/status_content.html:16
#: bookwyrm/templates/snippets/trimmed_text.html:12
#: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more"
msgstr "Déplier"
#: bookwyrm/templates/snippets/status/status_content.html:23
#: bookwyrm/templates/snippets/trimmed_text.html:18
#: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less"
msgstr "Replier"
#: bookwyrm/templates/snippets/status/status_content.html:44
#: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window"
msgstr "Ouvrir limage dans une nouvelle fenêtre"
#: bookwyrm/templates/snippets/status/status_header.html:22
#, fuzzy, python-format
#| msgid "favorited your <a href=\"%(related_path)s\">%(preview_name)s</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">review</a>"
msgstr "Messages directs avec <a href=\"%(path)s\">%(username)s</a>"
#: bookwyrm/templates/snippets/status/status_header.html:24
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">comment</a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">statut</a>"
#: bookwyrm/templates/snippets/status/status_header.html:26
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">quote</a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">statut</a>"
#: bookwyrm/templates/snippets/status/status_header.html:28
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">status</a>"
msgstr "<a href=\"%(related_path)s\">a répondu</a> à votre <a href=\"%(parent_path)s\">statut</a>"
#: bookwyrm/templates/snippets/status/status_options.html:7
#: bookwyrm/templates/snippets/user_options.html:7
msgid "More options"
msgstr "Plus doptions"
#: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status"
msgstr "Supprimer le statut"
@ -1749,8 +1771,6 @@ msgstr "Livres tagués « %(tag.name)s»"
#: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf"
msgstr "Créer létagère"
@ -1764,12 +1784,10 @@ msgstr "Mettre létagère à jour"
#: bookwyrm/templates/user/followers.html:7
#: bookwyrm/templates/user/following.html:7 bookwyrm/templates/user/user.html:9
#, fuzzy
#| msgid "User profile"
msgid "User Profile"
msgstr "Profil"
#: bookwyrm/templates/user/followers.html:26
#: bookwyrm/templates/user/followers.html:29
#, python-format
msgid "%(username)s has no followers"
msgstr "%(username)s na pas dabonné(e)"
@ -1778,14 +1796,12 @@ msgstr "%(username)s na pas dabonné(e)"
msgid "Following"
msgstr "Abonné(e) à"
#: bookwyrm/templates/user/following.html:26
#: bookwyrm/templates/user/following.html:29
#, python-format
msgid "%(username)s isn't following any users"
msgstr "%(username)s nest abonné(e) à personne"
#: bookwyrm/templates/user/lists.html:9
#, fuzzy
#| msgid "Your lists"
msgid "Your Lists"
msgstr "Vos listes"
@ -1800,14 +1816,11 @@ msgid "Create list"
msgstr "Créer une liste"
#: bookwyrm/templates/user/shelf.html:9
#, fuzzy
#| msgid "Your shelves"
msgid "Your Shelves"
msgstr "Vos étagères"
#: bookwyrm/templates/user/shelf.html:11
#, fuzzy, python-format
#| msgid "%(username)s has no followers"
#, python-format
msgid "%(username)s: Shelves"
msgstr "%(username)s: Étagères"
@ -1816,8 +1829,6 @@ msgid "Create shelf"
msgstr "Créer létagère"
#: bookwyrm/templates/user/shelf.html:54
#, fuzzy
#| msgid "Edit Shelf"
msgid "Edit shelf"
msgstr "Modifier létagère"
@ -1887,6 +1898,12 @@ msgstr[1] "%(username)s na pas dabonné(e)s"
msgid "%(counter)s following"
msgstr "%(counter)s abonnements"
#~ msgid "Created and curated by"
#~ msgstr "Créée et modérée par"
#~ msgid "Created by"
#~ msgstr "Créée par"
#~ msgid "Create New Shelf"
#~ msgstr "Créer une nouvelle étagère"

Binary file not shown.

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-02 21:36+0000\n"
"POT-Creation-Date: 2021-03-07 23:40+0000\n"
"PO-Revision-Date: 2021-03-02 10:35+0000\n"
"Last-Translator: Kana <gudzpoz@live.com>\n"
"Language-Team: Mouse Reeve <LL@li.org>\n"
@ -55,11 +55,9 @@ msgstr ""
msgid "%(value)s is not a valid username"
msgstr ""
#: bookwyrm/models/fields.py:164
#, fuzzy
#| msgid "Username:"
#: bookwyrm/models/fields.py:164 bookwyrm/templates/layout.html:152
msgid "username"
msgstr "用户名:"
msgstr "用户名"
#: bookwyrm/models/fields.py:169
msgid "A user with that username already exists."
@ -74,10 +72,14 @@ msgid "German"
msgstr ""
#: bookwyrm/settings.py:144
msgid "French"
msgid "Spanish"
msgstr ""
#: bookwyrm/settings.py:145
msgid "French"
msgstr ""
#: bookwyrm/settings.py:146
msgid "Simplified Chinese"
msgstr ""
@ -96,6 +98,8 @@ msgid "Books by %(name)s"
msgstr "%(name)s 所著的书"
#: bookwyrm/templates/book.html:21
#: bookwyrm/templates/discover/large-book.html:12
#: bookwyrm/templates/discover/small-book.html:9
msgid "by"
msgstr ""
@ -229,7 +233,7 @@ msgstr "地点"
#: bookwyrm/templates/book.html:229 bookwyrm/templates/layout.html:64
#: bookwyrm/templates/lists/lists.html:4 bookwyrm/templates/lists/lists.html:9
#: bookwyrm/templates/search_results.html:90
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/user/user_layout.html:62
msgid "Lists"
msgstr "列表"
@ -427,7 +431,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信"
#: bookwyrm/templates/feed/direct_messages.html:10
#: bookwyrm/templates/layout.html:79
#: bookwyrm/templates/layout.html:87
msgid "Direct Messages"
msgstr "私信"
@ -537,7 +541,7 @@ msgid "%(username)s's %(year)s Books"
msgstr "%(username)s 在 %(year)s 的书目"
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
#: bookwyrm/templates/layout.html:94
#: bookwyrm/templates/layout.html:102
msgid "Import Books"
msgstr "导入书目"
@ -594,35 +598,40 @@ msgstr "(按下重新加载来更新!)"
msgid "Failed to load"
msgstr "加载失败"
#: bookwyrm/templates/import_status.html:59
#: bookwyrm/templates/import_status.html:44
#, python-format
msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import."
msgstr ""
#: bookwyrm/templates/import_status.html:79
msgid "Select all"
msgstr "全选"
#: bookwyrm/templates/import_status.html:62
#: bookwyrm/templates/import_status.html:82
msgid "Retry items"
msgstr "重试项目"
#: bookwyrm/templates/import_status.html:84
#: bookwyrm/templates/import_status.html:108
msgid "Successfully imported"
msgstr "成功导入了"
#: bookwyrm/templates/import_status.html:88
#: bookwyrm/templates/import_status.html:112
#: bookwyrm/templates/lists/curate.html:14
msgid "Book"
msgstr "书目"
#: bookwyrm/templates/import_status.html:91
#: bookwyrm/templates/import_status.html:115
#: bookwyrm/templates/snippets/create_status_form.html:10
#: bookwyrm/templates/snippets/shelf.html:10
msgid "Title"
msgstr "标题"
#: bookwyrm/templates/import_status.html:94
#: bookwyrm/templates/import_status.html:118
#: bookwyrm/templates/snippets/shelf.html:11
msgid "Author"
msgstr "作者"
#: bookwyrm/templates/import_status.html:117
#: bookwyrm/templates/import_status.html:141
msgid "Imported"
msgstr "已导入"
@ -639,6 +648,28 @@ msgstr "没有权限"
msgid "Sorry! This invite code is no longer valid."
msgstr "抱歉!此邀请码已不再有效。"
#: bookwyrm/templates/isbn_search_results.html:4
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr "搜索结果"
#: bookwyrm/templates/isbn_search_results.html:9
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "\"%(query)s\" 的搜索结果"
#: bookwyrm/templates/isbn_search_results.html:14
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "匹配的书目"
#: bookwyrm/templates/isbn_search_results.html:17
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "没有找到 \"%(query)s\" 的书目"
#: bookwyrm/templates/layout.html:33
msgid "Search for a book or user"
msgstr "搜索书目或用户"
@ -660,55 +691,72 @@ msgstr "你的书架"
msgid "Feed"
msgstr "动态"
#: bookwyrm/templates/layout.html:84
#: bookwyrm/templates/layout.html:92
#: bookwyrm/templates/preferences/preferences_layout.html:14
msgid "Profile"
msgstr "个人资料"
#: bookwyrm/templates/layout.html:89
#: bookwyrm/templates/layout.html:97
msgid "Settings"
msgstr "设置"
#: bookwyrm/templates/layout.html:103
#: bookwyrm/templates/layout.html:111
#: bookwyrm/templates/settings/admin_layout.html:19
#: bookwyrm/templates/settings/manage_invites.html:3
msgid "Invites"
msgstr "邀请"
#: bookwyrm/templates/layout.html:110
#: bookwyrm/templates/layout.html:118
msgid "Site Configuration"
msgstr "站点配置"
#: bookwyrm/templates/layout.html:117
#: bookwyrm/templates/layout.html:125
msgid "Log out"
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:10
msgid "Notifications"
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/snippets/register_form.html:4
msgid "Username:"
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
msgid "Log in"
msgstr "登录"
#: bookwyrm/templates/layout.html:183
#: bookwyrm/templates/layout.html:168
msgid "Join"
msgstr ""
#: bookwyrm/templates/layout.html:191
msgid "About this server"
msgstr "关于本服务器"
#: bookwyrm/templates/layout.html:187
#: bookwyrm/templates/layout.html:195
msgid "Contact site admin"
msgstr "联系站点管理员"
#: bookwyrm/templates/layout.html:198
#: bookwyrm/templates/layout.html:202
#, python-format
msgid "Support %(site_name)s on <a href=\"%(support_link)s\" target=\"_blank\">%(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>."
msgstr "BookWyrm 是开源软件。你可以在<a href=\"https://github.com/mouse-reeve/bookwyrm\">GitHub</a> 贡献或报告问题。"
@ -717,6 +765,18 @@ msgstr "BookWyrm 是开源软件。你可以在<a href=\"https://github.com/mous
msgid "Create List"
msgstr "创建列表"
#: bookwyrm/templates/lists/created_text.html:5
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "Created and curated by <a href=\"%(path)s\">%(username)s</a>"
msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信"
#: bookwyrm/templates/lists/created_text.html:7
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "Created by <a href=\"%(path)s\">%(username)s</a>"
msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信"
#: bookwyrm/templates/lists/curate.html:6
msgid "Pending Books"
msgstr "等候中的书目"
@ -742,7 +802,7 @@ msgid "Discard"
msgstr "削除"
#: bookwyrm/templates/lists/edit_form.html:5
#: bookwyrm/templates/lists/list_layout.html:17
#: bookwyrm/templates/lists/list_layout.html:18
msgid "Edit List"
msgstr "编辑列表"
@ -821,16 +881,6 @@ msgstr "没有找到书目"
msgid "Suggest"
msgstr "推荐"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created and curated by"
msgstr "创建者及策展者为"
#: bookwyrm/templates/lists/list_items.html:19
#: bookwyrm/templates/lists/list_layout.html:11
msgid "Created by"
msgstr "创建者为"
#: bookwyrm/templates/lists/lists.html:14
msgid "Your lists"
msgstr "你的列表"
@ -854,10 +904,6 @@ msgstr "登录"
msgid "Password:"
msgstr "密码:"
#: bookwyrm/templates/login.html:36
msgid "Forgot your password?"
msgstr "忘记了密码?"
#: bookwyrm/templates/login.html:49
msgid "Contact an administrator to get an invite"
msgstr "联系管理员以取得邀请"
@ -871,117 +917,117 @@ msgid "Not Found"
msgstr "未找到"
#: 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 "你请求的页面似乎并不存在!"
#: bookwyrm/templates/notifications.html:14
msgid "Delete notifications"
msgstr "删除通知"
#: bookwyrm/templates/notifications.html:49
#: bookwyrm/templates/notifications.html:51
#, python-format
msgid "favorited 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>"
#: bookwyrm/templates/notifications.html:51
#: bookwyrm/templates/notifications.html:53
#, python-format
msgid "favorited 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>"
#: bookwyrm/templates/notifications.html:53
#: bookwyrm/templates/notifications.html:55
#, python-format
msgid "favorited 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>"
#: bookwyrm/templates/notifications.html:55
#: bookwyrm/templates/notifications.html:57
#, python-format
msgid "favorited your <a href=\"%(related_path)s\">status</a>"
msgstr "喜欢了你的 <a href=\"%(related_path)s\">状态</a>"
#: bookwyrm/templates/notifications.html:60
#: bookwyrm/templates/notifications.html:62
#, python-format
msgid "mentioned you in a <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> 里提到了你"
#: bookwyrm/templates/notifications.html:62
#: bookwyrm/templates/notifications.html:64
#, python-format
msgid "mentioned you in a <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> 里提到了你"
#: bookwyrm/templates/notifications.html:64
#: bookwyrm/templates/notifications.html:66
#, python-format
msgid "mentioned you in a <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> 中提到了你"
#: bookwyrm/templates/notifications.html:66
#: bookwyrm/templates/notifications.html:68
#, python-format
msgid "mentioned you in a <a href=\"%(related_path)s\">status</a>"
msgstr "在 <a href=\"%(related_path)s\">状态</a> 中提到了你"
#: bookwyrm/templates/notifications.html:71
#: bookwyrm/templates/notifications.html:73
#, python-format
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> 了你的 <a href=\"%(parent_path)s\">对 <em>%(book_title)s</em> 的书评</a>"
#: bookwyrm/templates/notifications.html:73
#: bookwyrm/templates/notifications.html:75
#, python-format
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> 了你的 <a href=\"%(parent_path)s\">对 <em>%(book_title)s</em> 的评论</a>"
#: bookwyrm/templates/notifications.html:75
#: bookwyrm/templates/notifications.html:77
#, python-format
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> 了你 <a href=\"%(parent_path)s\">对 <em>%(book_title)s</em> 中的引用</a>"
#: bookwyrm/templates/notifications.html:77
#: bookwyrm/templates/notifications.html:79
#, python-format
msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgstr "<a href=\"%(related_path)s\">回复</a> 了你的 <a href=\"%(parent_path)s\">状态</a>"
#: bookwyrm/templates/notifications.html:81
#: bookwyrm/templates/notifications.html:83
msgid "followed you"
msgstr "关注了你"
#: bookwyrm/templates/notifications.html:84
#: bookwyrm/templates/notifications.html:86
msgid "sent you a follow request"
msgstr "向你发送了关注请求"
#: bookwyrm/templates/notifications.html:90
#, python-format
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>"
#: bookwyrm/templates/notifications.html:92
#, python-format
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>"
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>"
#: bookwyrm/templates/notifications.html:94
#, python-format
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>"
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>"
#: bookwyrm/templates/notifications.html:96
#, python-format
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>"
#: bookwyrm/templates/notifications.html:98
#, python-format
msgid "boosted your <a href=\"%(related_path)s\">status</a>"
msgstr "转发了你的 <a href=\"%(related_path)s\">状态</a>"
#: bookwyrm/templates/notifications.html:100
#: bookwyrm/templates/notifications.html:102
#, python-format
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 " 添加了 <em><a href=\"%(book_path)s\">%(book_title)s</a></em> 到你的列表 \"<a href=\"%(list_path)s\">%(list_name)s</a>\""
#: bookwyrm/templates/notifications.html:102
#: bookwyrm/templates/notifications.html:104
#, python-format
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 " 推荐添加 <em><a href=\"%(book_path)s\">%(book_title)s</a></em> 到你的列表 \"<a href=\"%(list_path)s/curate\">%(list_name)s</a>\""
#: bookwyrm/templates/notifications.html:106
#: bookwyrm/templates/notifications.html:108
#, python-format
msgid " your <a href=\"/import/%(related_id)s\">import</a> completed."
msgstr " 你的 <a href=\"/import/%(related_id)s\">导入</a> 已完成。"
#: bookwyrm/templates/notifications.html:138
#: bookwyrm/templates/notifications.html:142
msgid "You're all caught up!"
msgstr "你什么也没错过!"
@ -989,7 +1035,6 @@ msgstr "你什么也没错过!"
#: bookwyrm/templates/password_reset.html:10
#: bookwyrm/templates/password_reset_request.html:4
#: bookwyrm/templates/password_reset_request.html:10
#, fuzzy
msgid "Reset Password"
msgstr "重设密码"
@ -1066,24 +1111,6 @@ msgstr "帐号"
msgid "Relationships"
msgstr "关系"
#: bookwyrm/templates/search_results.html:4
msgid "Search Results"
msgstr "搜索结果"
#: bookwyrm/templates/search_results.html:9
#, python-format
msgid "Search Results for \"%(query)s\""
msgstr "\"%(query)s\" 的搜索结果"
#: bookwyrm/templates/search_results.html:14
msgid "Matching Books"
msgstr "匹配的书目"
#: bookwyrm/templates/search_results.html:17
#, python-format
msgid "No books found for \"%(query)s\""
msgstr "没有找到 \"%(query)s\" 的书目"
#: bookwyrm/templates/search_results.html:33
msgid "Didn't find what you were looking for?"
msgstr "没有找到你想找的?"
@ -1109,7 +1136,7 @@ msgstr "匹配的用户"
msgid "No users found for \"%(query)s\""
msgstr "没有找到 \"%(query)s\" 的用户"
#: bookwyrm/templates/search_results.html:92
#: bookwyrm/templates/search_results.html:94
#, python-format
msgid "No lists found for \"%(query)s\""
msgstr "没有找到 \"%(query)s\" 的条目"
@ -1541,22 +1568,22 @@ msgid "Sign Up"
msgstr "注册"
#: bookwyrm/templates/snippets/rss_title.html:5
#: bookwyrm/templates/snippets/status/status_header.html:9
#: bookwyrm/templates/snippets/status/status_header.html:11
msgid "rated"
msgstr "评价了"
#: bookwyrm/templates/snippets/rss_title.html:7
#: bookwyrm/templates/snippets/status/status_header.html:11
#: bookwyrm/templates/snippets/status/status_header.html:13
msgid "reviewed"
msgstr "写了书评给"
#: bookwyrm/templates/snippets/rss_title.html:9
#: bookwyrm/templates/snippets/status/status_header.html:13
#: bookwyrm/templates/snippets/status/status_header.html:15
msgid "commented on"
msgstr "评论了"
#: bookwyrm/templates/snippets/rss_title.html:11
#: bookwyrm/templates/snippets/status/status_header.html:15
#: bookwyrm/templates/snippets/status/status_header.html:17
msgid "quoted"
msgstr "引用了"
@ -1637,7 +1664,7 @@ msgstr "开始 \"<em>%(book_title)s</em>\""
msgid "Want to Read \"<em>%(book_title)s</em>\""
msgstr "想要阅读 \"<em>%(book_title)s</em>\""
#: bookwyrm/templates/snippets/status/status.html:7
#: bookwyrm/templates/snippets/status/status.html:9
msgid "boosted"
msgstr "转发了"
@ -1647,28 +1674,50 @@ msgstr "转发了"
msgid "Reply"
msgstr "回复"
#: bookwyrm/templates/snippets/status/status_content.html:16
#: bookwyrm/templates/snippets/trimmed_text.html:12
#: bookwyrm/templates/snippets/status/status_content.html:18
#: bookwyrm/templates/snippets/trimmed_text.html:15
msgid "Show more"
msgstr "显示更多"
#: bookwyrm/templates/snippets/status/status_content.html:23
#: bookwyrm/templates/snippets/trimmed_text.html:18
#: bookwyrm/templates/snippets/status/status_content.html:25
#: bookwyrm/templates/snippets/trimmed_text.html:25
msgid "Show less"
msgstr "显示更少"
#: bookwyrm/templates/snippets/status/status_content.html:44
#: bookwyrm/templates/snippets/status/status_content.html:46
msgid "Open image in new window"
msgstr "在新窗口中打开图像"
#: bookwyrm/templates/snippets/status/status_header.html:22
#, fuzzy, python-format
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">review</a>"
msgstr "与 <a href=\"%(path)s\">%(username)s</a> 私信"
#: bookwyrm/templates/snippets/status/status_header.html:24
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">comment</a>"
msgstr "<a href=\"%(related_path)s\">回复</a> 了你的 <a href=\"%(parent_path)s\">状态</a>"
#: bookwyrm/templates/snippets/status/status_header.html:26
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">quote</a>"
msgstr "<a href=\"%(related_path)s\">回复</a> 了你的 <a href=\"%(parent_path)s\">状态</a>"
#: bookwyrm/templates/snippets/status/status_header.html:28
#, fuzzy, python-format
#| msgid "<a href=\"%(related_path)s\">replied</a> to your <a href=\"%(parent_path)s\">status</a>"
msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">status</a>"
msgstr "<a href=\"%(related_path)s\">回复</a> 了你的 <a href=\"%(parent_path)s\">状态</a>"
#: bookwyrm/templates/snippets/status/status_options.html:7
#: bookwyrm/templates/snippets/user_options.html:7
msgid "More options"
msgstr "更多选项"
#: bookwyrm/templates/snippets/status/status_options.html:17
#, fuzzy
#| msgid "Delete post"
msgid "Delete status"
msgstr "删除发文"
@ -1692,8 +1741,6 @@ msgstr "标有 \"%(tag.name)s\" 标签的书"
#: bookwyrm/templates/user/create_shelf_form.html:5
#: bookwyrm/templates/user/create_shelf_form.html:22
#, fuzzy
#| msgid "Create shelf"
msgid "Create Shelf"
msgstr "创建书架"
@ -1710,7 +1757,7 @@ msgstr "更新书架"
msgid "User Profile"
msgstr "用户个人资料"
#: bookwyrm/templates/user/followers.html:26
#: bookwyrm/templates/user/followers.html:29
#, python-format
msgid "%(username)s has no followers"
msgstr "%(username)s 没有关注者"
@ -1719,7 +1766,7 @@ msgstr "%(username)s 没有关注者"
msgid "Following"
msgstr "正在关注"
#: bookwyrm/templates/user/following.html:26
#: bookwyrm/templates/user/following.html:29
#, python-format
msgid "%(username)s isn't following any users"
msgstr "%(username)s 没有关注任何用户"
@ -1818,6 +1865,12 @@ msgstr[0] "%(counter)s 个关注者"
msgid "%(counter)s following"
msgstr "关注着 %(counter)s 人"
#~ msgid "Created and curated by"
#~ msgstr "创建者及策展者为"
#~ msgid "Created by"
#~ msgstr "创建者为"
#~ msgid "Create New Shelf"
#~ msgstr "新建书架"