forked from mirrors/bookwyrm
Merge branch 'main' into opengraph-image-generation
This commit is contained in:
commit
973b23856c
86 changed files with 2188 additions and 1834 deletions
|
@ -13,16 +13,10 @@ DEFAULT_LANGUAGE="English"
|
|||
## Leave unset to allow all hosts
|
||||
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
||||
|
||||
OL_URL=https://openlibrary.org
|
||||
|
||||
## Database backend to use.
|
||||
## Default is postgres, sqlite is for dev quickstart only (NOT production!!!)
|
||||
BOOKWYRM_DATABASE_BACKEND=postgres
|
||||
|
||||
MEDIA_ROOT=images/
|
||||
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_PASSWORD=fedireads
|
||||
POSTGRES_PASSWORD=securedbypassword123
|
||||
POSTGRES_USER=fedireads
|
||||
POSTGRES_DB=fedireads
|
||||
POSTGRES_HOST=db
|
||||
|
@ -34,10 +28,8 @@ REDIS_ACTIVITY_PORT=6379
|
|||
#REDIS_ACTIVITY_PASSWORD=redispassword345
|
||||
|
||||
# Redis as celery broker
|
||||
#REDIS_BROKER_PORT=6379
|
||||
REDIS_BROKER_PORT=6379
|
||||
#REDIS_BROKER_PASSWORD=redispassword123
|
||||
CELERY_BROKER=redis://redis_broker:6379/0
|
||||
CELERY_RESULT_BACKEND=redis://redis_broker:6379/0
|
||||
|
||||
FLOWER_PORT=8888
|
||||
#FLOWER_USER=mouse
|
||||
|
@ -50,9 +42,6 @@ EMAIL_HOST_PASSWORD=emailpassword123
|
|||
EMAIL_USE_TLS=true
|
||||
EMAIL_USE_SSL=false
|
||||
|
||||
# Set this to true when initializing certbot for domain, false when not
|
||||
CERTBOT_INIT=false
|
||||
|
||||
# Preview image generation can be computing and storage intensive
|
||||
# ENABLE_PREVIEW_IMAGES=True
|
||||
|
||||
|
@ -63,4 +52,4 @@ PREVIEW_BG_COLOR=use_dominant_color_light
|
|||
PREVIEW_TEXT_COLOR=#363636
|
||||
PREVIEW_IMG_WIDTH=1200
|
||||
PREVIEW_IMG_HEIGHT=630
|
||||
PREVIEW_DEFAULT_COVER_COLOR=#002549
|
||||
PREVIEW_DEFAULT_COVER_COLOR=#002549
|
|
@ -13,16 +13,10 @@ DEFAULT_LANGUAGE="English"
|
|||
## Leave unset to allow all hosts
|
||||
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
|
||||
|
||||
OL_URL=https://openlibrary.org
|
||||
|
||||
## Database backend to use.
|
||||
## Default is postgres, sqlite is for dev quickstart only (NOT production!!!)
|
||||
BOOKWYRM_DATABASE_BACKEND=postgres
|
||||
|
||||
MEDIA_ROOT=images/
|
||||
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_PASSWORD=securedbpassword123
|
||||
POSTGRES_PASSWORD=securedbypassword123
|
||||
POSTGRES_USER=fedireads
|
||||
POSTGRES_DB=fedireads
|
||||
POSTGRES_HOST=db
|
||||
|
@ -36,8 +30,6 @@ REDIS_ACTIVITY_PASSWORD=redispassword345
|
|||
# Redis as celery broker
|
||||
REDIS_BROKER_PORT=6379
|
||||
REDIS_BROKER_PASSWORD=redispassword123
|
||||
CELERY_BROKER=redis://:${REDIS_BROKER_PASSWORD}@redis_broker:${REDIS_BROKER_PORT}/0
|
||||
CELERY_RESULT_BACKEND=redis://:${REDIS_BROKER_PASSWORD}@redis_broker:${REDIS_BROKER_PORT}/0
|
||||
|
||||
FLOWER_PORT=8888
|
||||
FLOWER_USER=mouse
|
||||
|
@ -50,9 +42,6 @@ EMAIL_HOST_PASSWORD=emailpassword123
|
|||
EMAIL_USE_TLS=true
|
||||
EMAIL_USE_SSL=false
|
||||
|
||||
# Set this to true when initializing certbot for domain, false when not
|
||||
CERTBOT_INIT=false
|
||||
|
||||
# Preview image generation can be computing and storage intensive
|
||||
# ENABLE_PREVIEW_IMAGES=True
|
||||
|
||||
|
@ -63,4 +52,4 @@ PREVIEW_BG_COLOR=use_dominant_color_light
|
|||
PREVIEW_TEXT_COLOR=#363636
|
||||
PREVIEW_IMG_WIDTH=1200
|
||||
PREVIEW_IMG_HEIGHT=630
|
||||
PREVIEW_DEFAULT_COVER_COLOR=#002549
|
||||
PREVIEW_DEFAULT_COVER_COLOR=#002549
|
4
.github/workflows/django-tests.yml
vendored
4
.github/workflows/django-tests.yml
vendored
|
@ -50,7 +50,6 @@ jobs:
|
|||
SECRET_KEY: beepbeep
|
||||
DEBUG: true
|
||||
DOMAIN: your.domain.here
|
||||
OL_URL: https://openlibrary.org
|
||||
BOOKWYRM_DATABASE_BACKEND: postgres
|
||||
MEDIA_ROOT: images/
|
||||
POSTGRES_PASSWORD: hunter2
|
||||
|
@ -58,7 +57,8 @@ jobs:
|
|||
POSTGRES_DB: github_actions
|
||||
POSTGRES_HOST: 127.0.0.1
|
||||
CELERY_BROKER: ""
|
||||
CELERY_RESULT_BACKEND: ""
|
||||
REDIS_BROKER_PORT: 6379
|
||||
FLOWER_PORT: 8888
|
||||
EMAIL_HOST: "smtp.mailgun.org"
|
||||
EMAIL_PORT: 587
|
||||
EMAIL_HOST_USER: ""
|
||||
|
|
|
@ -9,5 +9,3 @@ WORKDIR /app
|
|||
COPY requirements.txt /app/
|
||||
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 ./celerywyrm /app/
|
||||
|
|
|
@ -201,6 +201,19 @@ def add_status_on_create(sender, instance, created, *args, **kwargs):
|
|||
for stream in streams.values():
|
||||
stream.add_status(instance)
|
||||
|
||||
if sender != models.Boost:
|
||||
return
|
||||
# remove the original post and other, earlier boosts
|
||||
boosted = instance.boost.boosted_status
|
||||
old_versions = models.Boost.objects.filter(
|
||||
boosted_status__id=boosted.id,
|
||||
created_date__lt=instance.created_date,
|
||||
)
|
||||
for stream in streams.values():
|
||||
stream.remove_object_from_related_stores(boosted)
|
||||
for status in old_versions:
|
||||
stream.remove_object_from_related_stores(status)
|
||||
|
||||
|
||||
@receiver(signals.post_delete, sender=models.Boost)
|
||||
# pylint: disable=unused-argument
|
||||
|
@ -208,7 +221,10 @@ def remove_boost_on_delete(sender, instance, *args, **kwargs):
|
|||
"""boosts are deleted"""
|
||||
# we're only interested in new statuses
|
||||
for stream in streams.values():
|
||||
# remove the boost
|
||||
stream.remove_object_from_related_stores(instance)
|
||||
# re-add the original status
|
||||
stream.add_status(instance.boosted_status)
|
||||
|
||||
|
||||
@receiver(signals.post_save, sender=models.UserFollows)
|
||||
|
|
|
@ -37,7 +37,7 @@ class AbstractMinimalConnector(ABC):
|
|||
for field in self_fields:
|
||||
setattr(self, field, getattr(info, field))
|
||||
|
||||
def search(self, query, min_confidence=None):
|
||||
def search(self, query, min_confidence=None, timeout=5):
|
||||
"""free text search"""
|
||||
params = {}
|
||||
if min_confidence:
|
||||
|
@ -46,6 +46,7 @@ class AbstractMinimalConnector(ABC):
|
|||
data = self.get_search_data(
|
||||
"%s%s" % (self.search_url, query),
|
||||
params=params,
|
||||
timeout=timeout,
|
||||
)
|
||||
results = []
|
||||
|
||||
|
@ -218,7 +219,7 @@ def dict_from_mappings(data, mappings):
|
|||
return result
|
||||
|
||||
|
||||
def get_data(url, params=None):
|
||||
def get_data(url, params=None, timeout=10):
|
||||
"""wrapper for request.get"""
|
||||
# check if the url is blocked
|
||||
if models.FederatedServer.is_blocked(url):
|
||||
|
@ -234,6 +235,7 @@ def get_data(url, params=None):
|
|||
"Accept": "application/json; charset=utf-8",
|
||||
"User-Agent": settings.USER_AGENT,
|
||||
},
|
||||
timeout=timeout,
|
||||
)
|
||||
except (RequestError, SSLError, ConnectionError) as e:
|
||||
logger.exception(e)
|
||||
|
@ -250,7 +252,7 @@ def get_data(url, params=None):
|
|||
return data
|
||||
|
||||
|
||||
def get_image(url):
|
||||
def get_image(url, timeout=10):
|
||||
"""wrapper for requesting an image"""
|
||||
try:
|
||||
resp = requests.get(
|
||||
|
@ -258,6 +260,7 @@ def get_image(url):
|
|||
headers={
|
||||
"User-Agent": settings.USER_AGENT,
|
||||
},
|
||||
timeout=timeout,
|
||||
)
|
||||
except (RequestError, SSLError) as e:
|
||||
logger.exception(e)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
""" interface with whatever connectors the app has """
|
||||
from datetime import datetime
|
||||
import importlib
|
||||
import logging
|
||||
import re
|
||||
|
@ -29,9 +30,11 @@ def search(query, min_confidence=0.1, return_first=False):
|
|||
isbn = re.sub(r"[\W_]", "", query)
|
||||
maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13
|
||||
|
||||
timeout = 15
|
||||
start_time = datetime.now()
|
||||
for connector in get_connectors():
|
||||
result_set = None
|
||||
if maybe_isbn and connector.isbn_search_url and connector.isbn_search_url == "":
|
||||
if maybe_isbn and connector.isbn_search_url and connector.isbn_search_url != "":
|
||||
# Search on ISBN
|
||||
try:
|
||||
result_set = connector.isbn_search(isbn)
|
||||
|
@ -59,6 +62,8 @@ def search(query, min_confidence=0.1, return_first=False):
|
|||
"results": result_set,
|
||||
}
|
||||
)
|
||||
if (datetime.now() - start_time).seconds >= timeout:
|
||||
break
|
||||
|
||||
if return_first:
|
||||
return None
|
||||
|
|
|
@ -3,7 +3,7 @@ from functools import reduce
|
|||
import operator
|
||||
|
||||
from django.contrib.postgres.search import SearchRank, SearchVector
|
||||
from django.db.models import Count, OuterRef, Subquery, F, Q
|
||||
from django.db.models import OuterRef, Subquery, F, Q
|
||||
|
||||
from bookwyrm import models
|
||||
from .abstract_connector import AbstractConnector, SearchResult
|
||||
|
@ -122,6 +122,8 @@ def search_identifiers(query, *filters):
|
|||
results = models.Edition.objects.filter(
|
||||
*filters, reduce(operator.or_, (Q(**f) for f in or_filters))
|
||||
).distinct()
|
||||
if results.count() <= 1:
|
||||
return results
|
||||
|
||||
# when there are multiple editions of the same work, pick the default.
|
||||
# it would be odd for this to happen.
|
||||
|
@ -146,19 +148,15 @@ def search_title_author(query, min_confidence, *filters):
|
|||
)
|
||||
|
||||
results = (
|
||||
models.Edition.objects.annotate(search=vector)
|
||||
.annotate(rank=SearchRank(vector, query))
|
||||
models.Edition.objects.annotate(rank=SearchRank(vector, query))
|
||||
.filter(*filters, rank__gt=min_confidence)
|
||||
.order_by("-rank")
|
||||
)
|
||||
|
||||
# when there are multiple editions of the same work, pick the closest
|
||||
editions_of_work = (
|
||||
results.values("parent_work")
|
||||
.annotate(Count("parent_work"))
|
||||
.values_list("parent_work")
|
||||
)
|
||||
editions_of_work = results.values("parent_work__id").values_list("parent_work__id")
|
||||
|
||||
# filter out multiple editions of the same work
|
||||
for work_id in set(editions_of_work):
|
||||
editions = results.filter(parent_work=work_id)
|
||||
default = editions.order_by("-edition_rank").first()
|
||||
|
|
|
@ -150,6 +150,12 @@ class LimitedEditUserForm(CustomForm):
|
|||
help_texts = {f: None for f in fields}
|
||||
|
||||
|
||||
class DeleteUserForm(CustomForm):
|
||||
class Meta:
|
||||
model = models.User
|
||||
fields = ["password"]
|
||||
|
||||
|
||||
class UserGroupForm(CustomForm):
|
||||
class Meta:
|
||||
model = models.User
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
""" activitypub-aware django model fields """
|
||||
from dataclasses import MISSING
|
||||
import imghdr
|
||||
import re
|
||||
from uuid import uuid4
|
||||
|
||||
|
@ -9,6 +10,7 @@ from django.contrib.postgres.fields import ArrayField as DjangoArrayField
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import models
|
||||
from django.forms import ClearableFileInput, ImageField as DjangoImageField
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from bookwyrm import activitypub
|
||||
|
@ -332,6 +334,18 @@ class TagField(ManyToManyField):
|
|||
return items
|
||||
|
||||
|
||||
class ClearableFileInputWithWarning(ClearableFileInput):
|
||||
"""max file size warning"""
|
||||
|
||||
template_name = "widgets/clearable_file_input_with_warning.html"
|
||||
|
||||
|
||||
class CustomImageField(DjangoImageField):
|
||||
"""overwrites image field for form"""
|
||||
|
||||
widget = ClearableFileInputWithWarning
|
||||
|
||||
|
||||
def image_serializer(value, alt):
|
||||
"""helper for serializing images"""
|
||||
if value and hasattr(value, "url"):
|
||||
|
@ -391,10 +405,19 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
|
|||
if not response:
|
||||
return None
|
||||
|
||||
image_name = str(uuid4()) + "." + url.split(".")[-1]
|
||||
image_content = ContentFile(response.content)
|
||||
image_name = str(uuid4()) + "." + imghdr.what(None, image_content.read())
|
||||
return [image_name, image_content]
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
"""special case for forms"""
|
||||
return super().formfield(
|
||||
**{
|
||||
"form_class": CustomImageField,
|
||||
**kwargs,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class DateTimeField(ActivitypubFieldMixin, models.DateTimeField):
|
||||
"""activitypub-aware datetime field"""
|
||||
|
|
|
@ -75,7 +75,12 @@ class ImportItem(models.Model):
|
|||
|
||||
def resolve(self):
|
||||
"""try various ways to lookup a book"""
|
||||
self.book = self.get_book_from_isbn() or self.get_book_from_title_author()
|
||||
if self.isbn:
|
||||
self.book = self.get_book_from_isbn()
|
||||
else:
|
||||
# don't fall back on title/author search is isbn is present.
|
||||
# you're too likely to mismatch
|
||||
self.get_book_from_title_author()
|
||||
|
||||
def get_book_from_isbn(self):
|
||||
"""search by isbn"""
|
||||
|
|
|
@ -14,13 +14,18 @@ PAGE_LENGTH = env("PAGE_LENGTH", 15)
|
|||
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")
|
||||
|
||||
# celery
|
||||
CELERY_BROKER = env("CELERY_BROKER")
|
||||
CELERY_RESULT_BACKEND = env("CELERY_RESULT_BACKEND")
|
||||
CELERY_BROKER = "redis://:{}@redis_broker:{}/0".format(
|
||||
requests.utils.quote(env("REDIS_BROKER_PASSWORD", "")), env("REDIS_BROKER_PORT")
|
||||
)
|
||||
CELERY_RESULT_BACKEND = "redis://:{}@redis_broker:{}/0".format(
|
||||
requests.utils.quote(env("REDIS_BROKER_PASSWORD", "")), env("REDIS_BROKER_PORT")
|
||||
)
|
||||
CELERY_ACCEPT_CONTENT = ["application/json"]
|
||||
CELERY_TASK_SERIALIZER = "json"
|
||||
CELERY_RESULT_SERIALIZER = "json"
|
||||
|
||||
# email
|
||||
EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend")
|
||||
EMAIL_HOST = env("EMAIL_HOST")
|
||||
EMAIL_PORT = env("EMAIL_PORT", 587)
|
||||
EMAIL_HOST_USER = env("EMAIL_HOST_USER")
|
||||
|
@ -55,7 +60,6 @@ SECRET_KEY = env("SECRET_KEY")
|
|||
DEBUG = env.bool("DEBUG", True)
|
||||
|
||||
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", ["*"])
|
||||
OL_URL = env("OL_URL")
|
||||
|
||||
# Application definition
|
||||
|
||||
|
@ -117,10 +121,8 @@ STREAMS = ["home", "local", "federated"]
|
|||
# Database
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
|
||||
|
||||
BOOKWYRM_DATABASE_BACKEND = env("BOOKWYRM_DATABASE_BACKEND", "postgres")
|
||||
|
||||
BOOKWYRM_DBS = {
|
||||
"postgres": {
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.postgresql_psycopg2",
|
||||
"NAME": env("POSTGRES_DB", "fedireads"),
|
||||
"USER": env("POSTGRES_USER", "fedireads"),
|
||||
|
@ -130,8 +132,6 @@ BOOKWYRM_DBS = {
|
|||
},
|
||||
}
|
||||
|
||||
DATABASES = {"default": BOOKWYRM_DBS[BOOKWYRM_DATABASE_BACKEND]}
|
||||
|
||||
|
||||
LOGIN_URL = "/login/"
|
||||
AUTH_USER_MODEL = "bookwyrm.User"
|
||||
|
@ -139,6 +139,7 @@ AUTH_USER_MODEL = "bookwyrm.User"
|
|||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
let BookWyrm = new class {
|
||||
constructor() {
|
||||
this.MAX_FILE_SIZE_BYTES = 10 * 1000000;
|
||||
this.initOnDOMLoaded();
|
||||
this.initReccuringTasks();
|
||||
this.initEventListeners();
|
||||
|
@ -32,15 +33,26 @@ let BookWyrm = new class {
|
|||
'click',
|
||||
this.back)
|
||||
);
|
||||
|
||||
document.querySelectorAll('input[type="file"]')
|
||||
.forEach(node => node.addEventListener(
|
||||
'change',
|
||||
this.disableIfTooLarge.bind(this)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute code once the DOM is loaded.
|
||||
*/
|
||||
initOnDOMLoaded() {
|
||||
const bookwyrm = this;
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('.tab-group')
|
||||
.forEach(tabs => new TabGroup(tabs));
|
||||
document.querySelectorAll('input[type="file"]').forEach(
|
||||
bookwyrm.disableIfTooLarge.bind(bookwyrm)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -126,6 +138,7 @@ let BookWyrm = new class {
|
|||
* @return {undefined}
|
||||
*/
|
||||
toggleAction(event) {
|
||||
event.preventDefault();
|
||||
let trigger = event.currentTarget;
|
||||
let pressed = trigger.getAttribute('aria-pressed') === 'false';
|
||||
let targetId = trigger.dataset.controls;
|
||||
|
@ -170,6 +183,8 @@ let BookWyrm = new class {
|
|||
if (focus) {
|
||||
this.toggleFocus(focus);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,4 +299,27 @@ let BookWyrm = new class {
|
|||
node.classList.remove(classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disableIfTooLarge(eventOrElement) {
|
||||
const { addRemoveClass, MAX_FILE_SIZE_BYTES } = this;
|
||||
const element = eventOrElement.currentTarget || eventOrElement;
|
||||
|
||||
const submits = element.form.querySelectorAll('[type="submit"]');
|
||||
const warns = element.parentElement.querySelectorAll('.file-too-big');
|
||||
const isTooBig = element.files &&
|
||||
element.files[0] &&
|
||||
element.files[0].size > MAX_FILE_SIZE_BYTES;
|
||||
|
||||
if (isTooBig) {
|
||||
submits.forEach(submitter => submitter.disabled = true);
|
||||
warns.forEach(
|
||||
sib => addRemoveClass(sib, 'is-hidden', false)
|
||||
);
|
||||
} else {
|
||||
submits.forEach(submitter => submitter.disabled = false);
|
||||
warns.forEach(
|
||||
sib => addRemoveClass(sib, 'is-hidden', true)
|
||||
);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
|
|
@ -17,7 +17,7 @@ let LocalStorageTools = new class {
|
|||
* @return {undefined}
|
||||
*/
|
||||
updateDisplay(event) {
|
||||
// used in set reading goal
|
||||
// Used in set reading goal
|
||||
let key = event.target.dataset.id;
|
||||
let value = event.target.dataset.value;
|
||||
|
||||
|
@ -34,10 +34,10 @@ let LocalStorageTools = new class {
|
|||
* @return {undefined}
|
||||
*/
|
||||
setDisplay(node) {
|
||||
// used in set reading goal
|
||||
// Used in set reading goal
|
||||
let key = node.dataset.hide;
|
||||
let value = window.localStorage.getItem(key);
|
||||
|
||||
BookWyrm.addRemoveClass(node, 'is-hidden', value);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
|
|
@ -15,49 +15,83 @@
|
|||
<div class="column is-narrow">
|
||||
<a href="{{ author.local_path }}/edit">
|
||||
<span class="icon icon-pencil" title="{% trans 'Edit Author' %}" aria-hidden="True"></span>
|
||||
<span>{% trans "Edit Author" %}</span>
|
||||
<span class="is-hidden-mobile">{% trans "Edit Author" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block content columns">
|
||||
{% if author.aliases or author.born or author.died or author.wikipedia_link %}
|
||||
<div class="column is-narrow">
|
||||
<div class="box">
|
||||
<div class="block columns" itemscope itemtype="https://schema.org/Person">
|
||||
<meta itemprop="name" content="{{ author.name }}">
|
||||
|
||||
{% if author.aliases or author.born or author.died or author.wikipedia_link or author.openlibrary_key or author.inventaire_id %}
|
||||
<div class="column is-two-fifths">
|
||||
<div class="box py-2">
|
||||
<dl>
|
||||
{% if author.aliases %}
|
||||
<div class="is-flex">
|
||||
<dt class="mr-1">{% trans "Aliases:" %}</dt>
|
||||
<dd itemprop="aliases">{{ author.aliases|join:', ' }}</dd>
|
||||
<div class="is-flex is-flex-wrap-wrap my-1">
|
||||
<dt class="has-text-weight-bold mr-1">{% trans "Aliases:" %}</dt>
|
||||
{% for alias in author.aliases %}
|
||||
<dd itemprop="alternateName" content="{{alias}}">
|
||||
{{alias}}{% if not forloop.last %}, {% endif %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if author.born %}
|
||||
<div class="is-flex">
|
||||
<dt class="mr-1">{% trans "Born:" %}</dt>
|
||||
<dd itemprop="aliases">{{ author.born|naturalday }}</dd>
|
||||
<div class="is-flex my-1">
|
||||
<dt class="has-text-weight-bold mr-1">{% trans "Born:" %}</dt>
|
||||
<dd itemprop="birthDate">{{ author.born|naturalday }}</dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if author.died %}
|
||||
<div class="is-flex">
|
||||
<dt class="mr-1">{% trans "Died:" %}</dt>
|
||||
<dd itemprop="aliases">{{ author.died|naturalday }}</dd>
|
||||
<div class="is-flex my-1">
|
||||
<dt class="has-text-weight-bold mr-1">{% trans "Died:" %}</dt>
|
||||
<dd itemprop="deathDate">{{ author.died|naturalday }}</dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
</dl>
|
||||
|
||||
{% if author.wikipedia_link %}
|
||||
<p><a href="{{ author.wikipedia_link }}" rel=”noopener” target="_blank">{% trans "Wikipedia" %}</a></p>
|
||||
{% endif %}
|
||||
{% if author.openlibrary_key %}
|
||||
<p class="mb-0">
|
||||
<a href="https://openlibrary.org/authors/{{ author.openlibrary_key }}" target="_blank" rel="noopener">{% trans "View on OpenLibrary" %}</a>
|
||||
<p class="my-1">
|
||||
<a itemprop="sameAs" href="{{ author.wikipedia_link }}" rel=”noopener” target="_blank">
|
||||
{% trans "Wikipedia" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if author.openlibrary_key %}
|
||||
<p class="my-1">
|
||||
<a itemprop="sameAs" href="https://openlibrary.org/authors/{{ author.openlibrary_key }}" target="_blank" rel="noopener">
|
||||
{% trans "View on OpenLibrary" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if author.inventaire_id %}
|
||||
<p class="mb-0">
|
||||
<a href="https://inventaire.io/entity/{{ author.inventaire_id }}" target="_blank" rel="noopener">{% trans "View on Inventaire" %}</a>
|
||||
<p class="my-1">
|
||||
<a itemprop="sameAs" href="https://inventaire.io/entity/{{ author.inventaire_id }}" target="_blank" rel="noopener">
|
||||
{% trans "View on Inventaire" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if author.librarything_key %}
|
||||
<p class="my-1">
|
||||
<a itemprop="sameAs" href="https://www.librarything.com/author/{{ author.librarything_key }}" target="_blank" rel="noopener">
|
||||
{% trans "View on LibraryThing" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if author.goodreads_key %}
|
||||
<p class="my-1">
|
||||
<a itemprop="sameAs" href="https://www.goodreads.com/author/show/{{ author.goodreads_key }}" target="_blank" rel="noopener">
|
||||
{% trans "View on Goodreads" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
@ -29,67 +29,85 @@
|
|||
<div class="columns">
|
||||
<div class="column">
|
||||
<h2 class="title is-4">{% trans "Metadata" %}</h2>
|
||||
<p class="mb-2"><label class="label" for="id_name">{% trans "Name:" %}</label> {{ form.name }}</p>
|
||||
{% for error in form.name.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_name">{% trans "Name:" %}</label>
|
||||
{{ form.name }}
|
||||
{% for error in form.name.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_aliases">{% trans "Aliases:" %}</label>
|
||||
{{ form.aliases }}
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
</p>
|
||||
{% for error in form.aliases.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.aliases.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_bio">{% trans "Bio:" %}</label> {{ form.bio }}</p>
|
||||
{% for error in form.bio.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_bio">{% trans "Bio:" %}</label>
|
||||
{{ form.bio }}
|
||||
{% for error in form.bio.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_wikipedia_link">{% trans "Wikipedia link:" %}</label> {{ form.wikipedia_link }}</p>
|
||||
<p class="field"><label class="label" for="id_wikipedia_link">{% trans "Wikipedia link:" %}</label> {{ form.wikipedia_link }}</p>
|
||||
{% for error in form.wikipedia_link.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_born">{% trans "Birth date:" %}</label>
|
||||
<input type="date" name="born" value="{{ form.born.value|date:'Y-m-d' }}" class="input" id="id_born">
|
||||
</p>
|
||||
{% for error in form.born.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.born.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_died">{% trans "Death date:" %}</label>
|
||||
<input type="date" name="died" value="{{ form.died.value|date:'Y-m-d' }}" class="input" id="id_died">
|
||||
</p>
|
||||
{% for error in form.died.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.died.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h2 class="title is-4">{% trans "Author Identifiers" %}</h2>
|
||||
<p class="mb-2"><label class="label" for="id_openlibrary_key">{% trans "Openlibrary key:" %}</label> {{ form.openlibrary_key }}</p>
|
||||
{% for error in form.openlibrary_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_openlibrary_key">{% trans "Openlibrary key:" %}</label>
|
||||
{{ form.openlibrary_key }}
|
||||
{% for error in form.openlibrary_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_inventaire_id">{% trans "Inventaire ID:" %}</label> {{ form.inventaire_id }}</p>
|
||||
{% for error in form.inventaire_id.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_inventaire_id">{% trans "Inventaire ID:" %}</label>
|
||||
{{ form.inventaire_id }}
|
||||
{% for error in form.inventaire_id.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_librarything_key">{% trans "Librarything key:" %}</label> {{ form.librarything_key }}</p>
|
||||
{% for error in form.librarything_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_librarything_key">{% trans "Librarything key:" %}</label>
|
||||
{{ form.librarything_key }}
|
||||
{% for error in form.librarything_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_goodreads_key">{% trans "Goodreads key:" %}</label> {{ form.goodreads_key }}</p>
|
||||
{% for error in form.goodreads_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_goodreads_key">{% trans "Goodreads key:" %}</label>
|
||||
{{ form.goodreads_key }}
|
||||
{% for error in form.goodreads_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,28 +12,36 @@
|
|||
<div class="block" itemscope itemtype="https://schema.org/Book">
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<h1 class="title">
|
||||
<span itemprop="name">
|
||||
{{ book.title }}{% if book.subtitle %}:
|
||||
<small>{{ book.subtitle }}</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
{% if book.series %}
|
||||
<meta itemprop="isPartOf" content="{{ book.series }}">
|
||||
<meta itemprop="volumeNumber" content="{{ book.series_number }}">
|
||||
|
||||
<small class="has-text-grey-dark">
|
||||
({{ book.series }}
|
||||
{% if book.series_number %} #{{ book.series_number }}{% endif %})
|
||||
</small>
|
||||
<br>
|
||||
{% endif %}
|
||||
<h1 class="title" itemprop="name">
|
||||
{{ book.title }}
|
||||
</h1>
|
||||
|
||||
{% if book.subtitle or book.series %}
|
||||
<p class="subtitle title is-5">
|
||||
{% if book.subtitle %}
|
||||
<meta
|
||||
itemprop="alternativeHeadline"
|
||||
content="{{ book.subtitle | escape }}"
|
||||
>
|
||||
|
||||
<span class="has-text-weight-bold">
|
||||
{{ book.subtitle }}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if book.series %}
|
||||
<meta itemprop="isPartOf" content="{{ book.series | escape }}">
|
||||
<meta itemprop="volumeNumber" content="{{ book.series_number }}">
|
||||
|
||||
({{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %})
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if book.authors %}
|
||||
<h2 class="subtitle">
|
||||
{% trans "by" %} {% include 'snippets/authors.html' with book=book %}
|
||||
</h2>
|
||||
<div class="subtitle">
|
||||
{% trans "by" %} {% include 'snippets/authors.html' with book=book %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -41,7 +49,7 @@
|
|||
<div class="column is-narrow">
|
||||
<a href="{{ book.id }}/edit">
|
||||
<span class="icon icon-pencil" title="{% trans "Edit Book" %}" aria-hidden=True></span>
|
||||
<span>{% trans "Edit Book" %}</span>
|
||||
<span class="is-hidden-mobile">{% trans "Edit Book" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -89,7 +97,7 @@
|
|||
|
||||
<div class="column is-three-fifths">
|
||||
<div class="block">
|
||||
<h3
|
||||
<div
|
||||
class="field is-grouped"
|
||||
itemprop="aggregateRating"
|
||||
itemscope
|
||||
|
@ -107,7 +115,7 @@
|
|||
{% plural %}
|
||||
({{ review_count }} reviews)
|
||||
{% endblocktrans %}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{% with full=book|book_description itemprop='abstract' %}
|
||||
{% include 'snippets/trimmed_text.html' %}
|
||||
|
@ -185,7 +193,7 @@
|
|||
<p>{% trans "You don't have any reading activity for this book." %}</p>
|
||||
{% endif %}
|
||||
{% for readthrough in readthroughs %}
|
||||
{% include 'snippets/readthrough.html' with readthrough=readthrough %}
|
||||
{% include 'book/readthrough.html' with readthrough=readthrough %}
|
||||
{% endfor %}
|
||||
</section>
|
||||
<hr aria-hidden="true">
|
||||
|
|
|
@ -14,11 +14,25 @@
|
|||
{% endif %}
|
||||
</h1>
|
||||
{% if book %}
|
||||
<div>
|
||||
<p>{% trans "Added:" %} {{ book.created_date | naturaltime }}</p>
|
||||
<p>{% trans "Updated:" %} {{ book.updated_date | naturaltime }}</p>
|
||||
<p>{% trans "Last edited by:" %} <a href="{{ book.last_edited_by.remote_id }}">{{ book.last_edited_by.display_name }}</a></p>
|
||||
</div>
|
||||
<dl>
|
||||
<div class="is-flex">
|
||||
<dt class="has-text-weight-semibold">{% trans "Added:" %}</dt>
|
||||
<dd class="ml-2">{{ book.created_date | naturaltime }}</dd>
|
||||
</div>
|
||||
|
||||
<div class="is-flex">
|
||||
<dt class="has-text-weight-semibold">{% trans "Updated:" %}</dt>
|
||||
<dd class="ml-2">{{ book.updated_date | naturaltime }}</dd>
|
||||
</div>
|
||||
|
||||
{% if book.last_edited_by %}
|
||||
<div class="is-flex">
|
||||
<dt class="has-text-weight-semibold">{% trans "Last edited by:" %}</dt>
|
||||
<dd class="ml-2"><a href="{{ book.last_edited_by.remote_id }}">{{ book.last_edited_by.display_name }}</a></dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</dl>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
|
@ -38,21 +52,28 @@
|
|||
{% if confirm_mode %}
|
||||
<div class="box">
|
||||
<h2 class="title is-4">{% trans "Confirm Book Info" %}</h2>
|
||||
<div class="columns">
|
||||
<div class="columns mb-4">
|
||||
{% if author_matches %}
|
||||
<input type="hidden" name="author-match-count" value="{{ author_matches|length }}">
|
||||
<div class="column is-half">
|
||||
{% for author in author_matches %}
|
||||
<fieldset class="mb-4">
|
||||
<legend class="title is-5 mb-1">{% blocktrans with name=author.name %}Is "{{ name }}" an existing author?{% endblocktrans %}</legend>
|
||||
<fieldset>
|
||||
<legend class="title is-5 mb-1">
|
||||
{% blocktrans with name=author.name %}Is "{{ name }}" an existing author?{% endblocktrans %}
|
||||
</legend>
|
||||
{% with forloop.counter0 as counter %}
|
||||
{% for match in author.matches %}
|
||||
<label><input type="radio" name="author_match-{{ counter }}" value="{{ match.id }}" required> {{ match.name }}</label>
|
||||
<label class="label mb-2">
|
||||
<input type="radio" name="author_match-{{ counter }}" value="{{ match.id }}" required>
|
||||
{{ match.name }}
|
||||
</label>
|
||||
<p class="help">
|
||||
<a href="{{ match.local_path }}" target="_blank">{% blocktrans with book_title=match.book_set.first.title %}Author of <em>{{ book_title }}</em>{% endblocktrans %}</a>
|
||||
</p>
|
||||
{% endfor %}
|
||||
<label><input type="radio" name="author_match-{{ counter }}" value="{{ author.name }}" required> {% trans "This is a new author" %}</label>
|
||||
<label class="label">
|
||||
<input type="radio" name="author_match-{{ counter }}" value="{{ author.name }}" required> {% trans "This is a new author" %}
|
||||
</label>
|
||||
{% endwith %}
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
|
@ -64,11 +85,17 @@
|
|||
{% if not book %}
|
||||
<div class="column is-half">
|
||||
<fieldset>
|
||||
<legend class="title is-5 mb-1">{% trans "Is this an edition of an existing work?" %}</legend>
|
||||
<legend class="title is-5 mb-1">
|
||||
{% trans "Is this an edition of an existing work?" %}
|
||||
</legend>
|
||||
{% for match in book_matches %}
|
||||
<label class="label"><input type="radio" name="parent_work" value="{{ match.parent_work.id }}"> {{ match.parent_work.title }}</label>
|
||||
<label class="label">
|
||||
<input type="radio" name="parent_work" value="{{ match.parent_work.id }}"> {{ match.parent_work.title }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
<label><input type="radio" name="parent_work" value="0" required> {% trans "This is a new work" %}</label>
|
||||
<label>
|
||||
<input type="radio" name="parent_work" value="0" required> {% trans "This is a new work" %}
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -89,76 +116,79 @@
|
|||
<section class="block">
|
||||
<h2 class="title is-4">{% trans "Metadata" %}</h2>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_title">{% trans "Title:" %}</label>
|
||||
<input type="text" name="title" value="{{ form.title.value|default:'' }}" maxlength="255" class="input" required="" id="id_title">
|
||||
</p>
|
||||
{% for error in form.title.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.title.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_subtitle">{% trans "Subtitle:" %}</label>
|
||||
<input type="text" name="subtitle" value="{{ form.subtitle.value|default:'' }}" maxlength="255" class="input" id="id_subtitle">
|
||||
</p>
|
||||
{% for error in form.subtitle.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.subtitle.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_description">{% trans "Description:" %}</label> {{ form.description }} </p>
|
||||
{% for error in form.description.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_description">{% trans "Description:" %}</label>
|
||||
{{ form.description }}
|
||||
{% for error in form.description.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_series">{% trans "Series:" %}</label>
|
||||
<input type="text" class="input" name="series" id="id_series" value="{{ form.series.value|default:'' }}">
|
||||
</p>
|
||||
{% for error in form.series.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.series.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_series_number">{% trans "Series number:" %}</label>
|
||||
{{ form.series_number }}
|
||||
</p>
|
||||
{% for error in form.series_number.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.series_number.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_languages">{% trans "Languages:" %}</label>
|
||||
{{ form.languages }}
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
</p>
|
||||
{% for error in form.languages.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.languages.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_publishers">{% trans "Publisher:" %}</label>
|
||||
{{ form.publishers }}
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
</p>
|
||||
{% for error in form.publishers.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.publishers.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_first_published_date">{% trans "First published date:" %}</label>
|
||||
<input type="date" name="first_published_date" class="input" id="id_first_published_date"{% if form.first_published_date.value %} value="{{ form.first_published_date.value|date:'Y-m-d' }}"{% endif %}>
|
||||
</p>
|
||||
{% for error in form.first_published_date.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.first_published_date.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
<div class="field">
|
||||
<label class="label" for="id_published_date">{% trans "Published date:" %}</label>
|
||||
<input type="date" name="published_date" class="input" id="id_published_date"{% if form.published_date.value %} value="{{ form.published_date.value|date:'Y-m-d'}}"{% endif %}>
|
||||
</p>
|
||||
{% for error in form.published_date.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.published_date.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
|
@ -166,16 +196,23 @@
|
|||
{% if book.authors.exists %}
|
||||
<fieldset>
|
||||
{% for author in book.authors.all %}
|
||||
<label class="label mb-2">
|
||||
<input type="checkbox" name="remove_authors" value="{{ author.id }}" {% if author.id|stringformat:"i" in remove_authors %}checked{% endif %}>
|
||||
{% blocktrans with name=author.name path=author.local_path %}Remove <a href="{{ path }}">{{ name }}</a>{% endblocktrans %}
|
||||
</label>
|
||||
<div class="is-flex is-justify-content-space-between">
|
||||
<label class="label mb-2">
|
||||
<input type="checkbox" name="remove_authors" value="{{ author.id }}" {% if author.id|stringformat:"i" in remove_authors %}checked{% endif %}>
|
||||
{% blocktrans with name=author.name %}Remove {{ name }}{% endblocktrans %}
|
||||
</label>
|
||||
<p class="help">
|
||||
<a href="{{ author.local_path }}">{% blocktrans with name=author.name %}Author page for {{ name }}{% endblocktrans %}</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<label class="label" for="id_add_author">{% trans "Add Authors:" %}</label>
|
||||
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'John Doe, Jane Smith' %}" value="{{ add_author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
<div class="field">
|
||||
<label class="label" for="id_add_author">{% trans "Add Authors:" %}</label>
|
||||
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'John Doe, Jane Smith' %}" value="{{ add_author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
@ -188,17 +225,17 @@
|
|||
|
||||
<div class="column">
|
||||
<div class="block">
|
||||
<p>
|
||||
<div class="field">
|
||||
<label class="label" for="id_cover">{% trans "Upload cover:" %}</label>
|
||||
{{ form.cover }}
|
||||
</p>
|
||||
</div>
|
||||
{% if book %}
|
||||
<p>
|
||||
<div class="field">
|
||||
<label class="label" for="id_cover_url">
|
||||
{% trans "Load cover from url:" %}
|
||||
</label>
|
||||
<input class="input" name="cover-url" id="id_cover_url">
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for error in form.cover.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
|
@ -209,51 +246,72 @@
|
|||
|
||||
<div class="block">
|
||||
<h2 class="title is-4">{% trans "Physical Properties" %}</h2>
|
||||
<p class="mb-2"><label class="label" for="id_physical_format">{% trans "Format:" %}</label> {{ form.physical_format }} </p>
|
||||
{% for error in form.physical_format.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
{% for error in form.physical_format.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_physical_format">{% trans "Format:" %}</label>
|
||||
{{ form.physical_format }}
|
||||
{% for error in form.physical_format.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_pages">{% trans "Pages:" %}</label> {{ form.pages }} </p>
|
||||
{% for error in form.pages.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_pages">{% trans "Pages:" %}</label>
|
||||
{{ form.pages }}
|
||||
{% for error in form.pages.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<h2 class="title is-4">{% trans "Book Identifiers" %}</h2>
|
||||
<p class="mb-2"><label class="label" for="id_isbn_13">{% trans "ISBN 13:" %}</label> {{ form.isbn_13 }} </p>
|
||||
{% for error in form.isbn_13.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_isbn_13">{% trans "ISBN 13:" %}</label>
|
||||
{{ form.isbn_13 }}
|
||||
{% for error in form.isbn_13.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_isbn_10">{% trans "ISBN 10:" %}</label> {{ form.isbn_10 }} </p>
|
||||
{% for error in form.isbn_10.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_isbn_10">{% trans "ISBN 10:" %}</label>
|
||||
{{ form.isbn_10 }}
|
||||
{% for error in form.isbn_10.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_openlibrary_key">{% trans "Openlibrary ID:" %}</label> {{ form.openlibrary_key }} </p>
|
||||
{% for error in form.openlibrary_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_openlibrary_key">{% trans "Openlibrary ID:" %}</label>
|
||||
{{ form.openlibrary_key }}
|
||||
{% for error in form.openlibrary_key.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_inventaire_id">{% trans "Inventaire ID:" %}</label> {{ form.inventaire_id }} </p>
|
||||
{% for error in form.inventaire_id.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_inventaire_id">{% trans "Inventaire ID:" %}</label>
|
||||
{{ form.inventaire_id }}
|
||||
{% for error in form.inventaire_id.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_oclc_number">{% trans "OCLC Number:" %}</label> {{ form.oclc_number }} </p>
|
||||
{% for error in form.oclc_number.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_oclc_number">{% trans "OCLC Number:" %}</label>
|
||||
{{ form.oclc_number }}
|
||||
{% for error in form.oclc_number.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="mb-2"><label class="label" for="id_asin">{% trans "ASIN:" %}</label> {{ form.asin }} </p>
|
||||
{% for error in form.ASIN.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_asin">{% trans "ASIN:" %}</label>
|
||||
{{ form.asin }}
|
||||
{% for error in form.ASIN.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -261,7 +319,7 @@
|
|||
{% if not confirm_mode %}
|
||||
<div class="block">
|
||||
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
|
||||
<a class="button" href="{{ book.local_path}}">{% trans "Cancel" %}</a>
|
||||
<a class="button" href="{{ book.local_path }}">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
|
||||
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True right=True %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{% load i18n %}
|
||||
{% load humanize %}
|
||||
{% load tz %}
|
||||
<div class="content box is-shadowless has-background-white-bis">
|
||||
<div id="hide-edit-readthrough-{{ readthrough.id }}">
|
||||
<div class="content">
|
||||
<div id="hide-edit-readthrough-{{ readthrough.id }}" class="box is-shadowless has-background-white-bis">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
{% trans "Progress Updates:" %}
|
|
@ -1,7 +1,7 @@
|
|||
{% load i18n %}
|
||||
<div
|
||||
role="dialog"
|
||||
class="modal is-hidden"
|
||||
class="modal {% if active %}is-active{% else %}is-hidden{% endif %}"
|
||||
id="{{ controls_text }}-{{ controls_uid }}"
|
||||
aria-labelledby="modal-card-title-{{ controls_text }}-{{ controls_uid }}"
|
||||
aria-modal="true"
|
||||
|
@ -11,7 +11,7 @@
|
|||
{% trans "Close" as label %}
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head" tabindex="0" id="modal-title-{{ controls_text }}-{{ controls_uid }}">
|
||||
<h2 class="modal-card-title" id="modal-card-title-{{ controls_text }}-{{ controls_uid }}">
|
||||
<h2 class="modal-card-title is-flex-shrink-1" id="modal-card-title-{{ controls_text }}-{{ controls_uid }}">
|
||||
{% block modal-title %}{% endblock %}
|
||||
</h2>
|
||||
{% include 'snippets/toggle/toggle_button.html' with label=label class="delete" nonbutton=True %}
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
{% csrf_token %}
|
||||
<button class="button is-primary" type="submit">Join Directory</button>
|
||||
<p class="help">
|
||||
{% url 'settings-profile' as path %}
|
||||
{% blocktrans %}You can opt-out at any time in your <a href="{{ path }}">profile settings.</a>{% endblocktrans %}
|
||||
{% url 'prefs-profile' as path %}
|
||||
{% blocktrans with path=path %}You can opt-out at any time in your <a href="{{ path }}">profile settings.</a>{% endblocktrans %}
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<p>{% trans "Privacy setting for imported reviews:" %}</p>
|
||||
<label>
|
||||
<span class="label">{% trans "Privacy setting for imported reviews:" %}</span>
|
||||
{% include 'snippets/privacy_select.html' with no_label=True %}
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -7,14 +7,19 @@
|
|||
{% block content %}{% spaceless %}
|
||||
<div class="block">
|
||||
<h1 class="title">{% trans "Import Status" %}</h1>
|
||||
<a href="{% url 'import' %}" class="has-text-weight-normal help subtitle is-link">{% trans "Back to imports" %}</a>
|
||||
|
||||
<p>
|
||||
{% trans "Import started:" %} {{ job.created_date | naturaltime }}
|
||||
</p>
|
||||
{% if job.complete %}
|
||||
<p>
|
||||
{% trans "Import completed:" %} {{ task.date_done | naturaltime }}
|
||||
</p>
|
||||
<dl>
|
||||
<div class="is-flex">
|
||||
<dt class="has-text-weight-medium">{% trans "Import started:" %}</dt>
|
||||
<dd class="ml-2">{{ job.created_date | naturaltime }}</dd>
|
||||
</div>
|
||||
{% if job.complete %}
|
||||
<div class="is-flex">
|
||||
<dt class="has-text-weight-medium">{% trans "Import completed:" %}</dt>
|
||||
<dd class="ml-2">{{ task.date_done | naturaltime }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{% elif task.failed %}
|
||||
<div class="notification is-danger">{% trans "TASK FAILED" %}</div>
|
||||
{% endif %}
|
||||
|
@ -22,8 +27,9 @@
|
|||
|
||||
<div class="block">
|
||||
{% if not job.complete %}
|
||||
{% trans "Import still in progress." %}
|
||||
<p>
|
||||
{% trans "Import still in progress." %}
|
||||
<br/>
|
||||
{% trans "(Hit reload to update!)" %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
@ -49,16 +55,13 @@
|
|||
<fieldset id="failed-imports">
|
||||
<ul>
|
||||
{% 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 }}">
|
||||
<label for="import-item-{{ item.id }}">
|
||||
Line {{ item.index }}:
|
||||
<strong>{{ item.data.Title }}</strong> by
|
||||
{{ item.data.Author }}
|
||||
</label>
|
||||
<p>
|
||||
<li class="mb-2 is-flex is-align-items-start">
|
||||
<input class="checkbox mt-1" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}">
|
||||
<label class="ml-1" for="import-item-{{ item.id }}">
|
||||
{% blocktrans with index=item.index title=item.data.Title author=item.data.Author %}Line {{ index }}: <strong>{{ title }}</strong> by {{ author }}{% endblocktrans %}
|
||||
<br/>
|
||||
{{ item.fail_reason }}.
|
||||
</p>
|
||||
</label>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -104,7 +107,11 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="block">
|
||||
{% if job.complete %}
|
||||
<h2 class="title is-4">{% trans "Successfully imported" %}</h2>
|
||||
{% else %}
|
||||
<h2 class="title is-4">{% trans "Import Progress" %}</h2>
|
||||
{% endif %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>
|
||||
|
|
|
@ -204,7 +204,7 @@
|
|||
<div class="columns">
|
||||
<div class="column is-one-fifth">
|
||||
<p>
|
||||
<a href="{% url 'about' %}">{% trans "About this server" %}</a>
|
||||
<a href="{% url 'about' %}">{% trans "About this instance" %}</a>
|
||||
</p>
|
||||
{% if site.admin_email %}
|
||||
<p>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block title %}
|
||||
{% if server %}
|
||||
{% blocktrans with server_name=server.server_name %}Reports: {{ server_name }}{% endblocktrans %}
|
||||
{% blocktrans with instance_name=server.server_name %}Reports: {{ instance_name }}{% endblocktrans %}
|
||||
{% else %}
|
||||
{% trans "Reports" %}
|
||||
{% endif %}
|
||||
|
@ -11,7 +11,7 @@
|
|||
|
||||
{% block header %}
|
||||
{% if server %}
|
||||
{% blocktrans with server_name=server.server_name %}Reports: <small>{{ server_name }}</small>{% endblocktrans %}
|
||||
{% blocktrans with instance_name=server.server_name %}Reports: <small>{{ instance_name }}</small>{% endblocktrans %}
|
||||
<a href="{% url 'settings-reports' %}" class="help has-text-weight-normal">Clear filters</a>
|
||||
{% else %}
|
||||
{% trans "Reports" %}
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<span class="icon icon-warning"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="column is-clipped">
|
||||
<div class="block">
|
||||
<p>
|
||||
{# DESCRIPTION #}
|
||||
|
@ -137,7 +137,7 @@
|
|||
{# PREVIEW #}
|
||||
<div class="notification py-2 {% if notification.id in unread %}is-primary is-light{% else %}has-background-white{% if notification.notification_type == 'REPLY' or notification.notification_type == 'MENTION' %} has-text-black{% else %}-bis has-text-grey-dark{% endif %}{% endif %}">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="column is-clipped">
|
||||
{% include 'snippets/status_preview.html' with status=related_status %}
|
||||
</div>
|
||||
<div class="column is-narrow {% if notification.notification_type == 'REPLY' or notification.notification_type == 'MENTION' %}has-text-black{% else %}has-text-grey-dark{% endif %}">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'preferences/preferences_layout.html' %}
|
||||
{% extends 'preferences/layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Blocked Users" %}{{ author.name }}{% endblock %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'preferences/preferences_layout.html' %}
|
||||
{% extends 'preferences/layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Change Password" %}{% endblock %}
|
||||
|
|
30
bookwyrm/templates/preferences/delete_user.html
Normal file
30
bookwyrm/templates/preferences/delete_user.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends 'preferences/layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Delete Account" %}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% trans "Delete Account" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
<div class="block">
|
||||
<h2 class="title is-4">{% trans "Permanently delete account" %}</h2>
|
||||
<p class="notification is-danger is-light">
|
||||
{% trans "Deleting your account cannot be undone. The username will not be available to register in the future." %}
|
||||
</p>
|
||||
|
||||
<form name="delete-user" action="{% url 'prefs-delete' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_password">{% trans "Confirm password:" %}</label>
|
||||
<input class="input {% if form.password.errors %}is-danger{% endif %}" type="password" name="password" id="id_password" required>
|
||||
{% for error in form.password.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="submit" class="button is-danger">{% trans "Delete Account" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'preferences/preferences_layout.html' %}
|
||||
{% extends 'preferences/layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Edit Profile" %}{% endblock %}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
{% url 'prefs-password' as url %}
|
||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Change Password" %}</a>
|
||||
</li>
|
||||
<li>
|
||||
{% url 'prefs-delete' as url %}
|
||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Delete Account" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 class="menu-label">{% trans "Relationships" %}</h2>
|
||||
<ul class="menu-list">
|
14
bookwyrm/templates/reading_progress/finish.html
Normal file
14
bookwyrm/templates/reading_progress/finish.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends 'layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{% blocktrans trimmed with book_title=book.title %}
|
||||
Finish "{{ book_title }}"
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "snippets/shelve_button/finish_reading_modal.html" with book=book active=True %}
|
||||
|
||||
{% endblock %}
|
14
bookwyrm/templates/reading_progress/start.html
Normal file
14
bookwyrm/templates/reading_progress/start.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends 'layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{% blocktrans trimmed with book_title=book.title %}
|
||||
Start "{{ book_title }}"
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "snippets/shelve_button/start_reading_modal.html" with book=book active=True %}
|
||||
|
||||
{% endblock %}
|
14
bookwyrm/templates/reading_progress/want.html
Normal file
14
bookwyrm/templates/reading_progress/want.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends 'layout.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{% blocktrans trimmed with book_title=book.title %}
|
||||
Want to Read "{{ book_title }}"
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "snippets/shelve_button/want_to_read_modal.html" with book=book active=True no_body=True %}
|
||||
|
||||
{% endblock %}
|
|
@ -36,7 +36,7 @@
|
|||
</li>
|
||||
<li>
|
||||
{% url 'settings-federation' as url %}
|
||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Federated Servers" %}</a>
|
||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Federated Instances" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{% extends 'settings/admin_layout.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Add server" %}{% endblock %}
|
||||
{% block title %}{% trans "Add instance" %}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% trans "Add server" %}
|
||||
<a href="{% url 'settings-federation' %}" class="has-text-weight-normal help">{% trans "Back to server list" %}</a>
|
||||
{% trans "Add instance" %}
|
||||
<a href="{% url 'settings-federation' %}" class="has-text-weight-normal help">{% trans "Back to instance list" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
|
@ -17,7 +17,7 @@
|
|||
</li>
|
||||
{% url 'settings-add-federated-server' as url %}
|
||||
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
|
||||
<a href="{{ url }}">{% trans "Add server" %}</a>
|
||||
<a href="{{ url }}">{% trans "Add instance" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -26,14 +26,14 @@
|
|||
{% csrf_token %}
|
||||
<div class="columns">
|
||||
<div class="column is-half">
|
||||
<div>
|
||||
<div class="field">
|
||||
<label class="label" for="id_server_name">{% trans "Instance:" %}</label>
|
||||
<input type="text" name="server_name" maxlength="255" class="input" required id="id_server_name" value="{{ form.server_name.value|default:'' }}" placeholder="domain.com">
|
||||
{% for error in form.server_name.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
<div class="field">
|
||||
<label class="label" for="id_status">{% trans "Status:" %}</label>
|
||||
<div class="select">
|
||||
<select name="status" class="" id="id_status">
|
||||
|
@ -44,14 +44,14 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<div>
|
||||
<div class="field">
|
||||
<label class="label" for="id_application_type">{% trans "Software:" %}</label>
|
||||
<input type="text" name="application_type" maxlength="255" class="input" id="id_application_type" value="{{ form.application_type.value|default:'' }}">
|
||||
{% for error in form.application_type.errors %}
|
||||
<p class="help is-danger">{{ error | escape }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
<div class="field">
|
||||
<label class="label" for="id_application_version">{% trans "Version:" %}</label>
|
||||
<input type="text" name="application_version" maxlength="255" class="input" id="id_application_version" value="{{ form.application_version.value|default:'' }}">
|
||||
{% for error in form.application_version.errors %}
|
||||
|
@ -60,10 +60,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<div class="field">
|
||||
<label class="label" for="id_notes">{% trans "Notes:" %}</label>
|
||||
<textarea name="notes" cols="None" rows="None" class="textarea" id="id_notes">{{ form.notes.value|default:'' }}</textarea>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="button is-primary">{% trans "Save" %}</button>
|
||||
</form>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{% extends 'settings/admin_layout.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Federated Servers" %}{% endblock %}
|
||||
{% block title %}{% trans "Federated Instances" %}{% endblock %}
|
||||
|
||||
{% block header %}{% trans "Federated Servers" %}{% endblock %}
|
||||
{% block header %}{% trans "Federated Instances" %}{% endblock %}
|
||||
|
||||
{% block edit-button %}
|
||||
<a href="{% url 'settings-import-blocklist' %}">
|
||||
<span class="icon icon-plus" title="{% trans 'Add server' %}" aria-hidden="True"></span>
|
||||
<span>{% trans "Add server" %}</span>
|
||||
<span class="icon icon-plus" title="{% trans 'Add instance' %}" aria-hidden="True"></span>
|
||||
<span class="is-hidden-mobile">{% trans "Add instance" %}</span>
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
<tr>
|
||||
{% url 'settings-federation' as url %}
|
||||
<th>
|
||||
{% trans "Server name" as text %}
|
||||
{% trans "Instance name" as text %}
|
||||
{% include 'snippets/table-sort-header.html' with field="server_name" sort=sort text=text %}
|
||||
</th>
|
||||
<th>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{% extends 'settings/admin_layout.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Add server" %}{% endblock %}
|
||||
{% block title %}{% trans "Add instance" %}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% trans "Import Blocklist" %}
|
||||
<a href="{% url 'settings-federation' %}" class="has-text-weight-normal help">{% trans "Back to server list" %}</a>
|
||||
<a href="{% url 'settings-federation' %}" class="has-text-weight-normal help">{% trans "Back to instance list" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
|
@ -17,7 +17,7 @@
|
|||
</li>
|
||||
{% url 'settings-add-federated-server' as url %}
|
||||
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
|
||||
<a href="{{ url }}">{% trans "Add server" %}</a>
|
||||
<a href="{{ url }}">{% trans "Add instance" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<pre>
|
||||
[
|
||||
{
|
||||
"instance": "example.server.com",
|
||||
"instance": "example.instance.com",
|
||||
"url": "https://link.to.more/info"
|
||||
},
|
||||
...
|
||||
|
|
|
@ -11,23 +11,23 @@
|
|||
{% csrf_token %}
|
||||
<section class="block" id="instance-info">
|
||||
<h2 class="title is-4">{% trans "Instance Info" %}</h2>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_name">{% trans "Instance Name:" %}</label>
|
||||
{{ site_form.name }}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_instance_tagline">{% trans "Tagline:" %}</label>
|
||||
{{ site_form.instance_tagline }}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_instance_description">{% trans "Instance description:" %}</label>
|
||||
{{ site_form.instance_description }}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_code_of_conduct">{% trans "Code of conduct:" %}</label>
|
||||
{{ site_form.code_of_conduct }}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_privacy_policy">{% trans "Privacy Policy:" %}</label>
|
||||
{{ site_form.privacy_policy }}
|
||||
</div>
|
||||
|
@ -57,19 +57,19 @@
|
|||
|
||||
<section class="block" id="footer">
|
||||
<h2 class="title is-4">{% trans "Footer Content" %}</h2>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_support_link">{% trans "Support link:" %}</label>
|
||||
<input type="text" name="support_link" maxlength="255" class="input" id="id_support_link" placeholder="https://www.patreon.com/bookwyrm"{% if site.support_link %} value="{{ site.support_link }}"{% endif %}>
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_support_title">{% trans "Support title:" %}</label>
|
||||
<input type="text" name="support_title" maxlength="100" class="input" id="id_support_title" placeholder="Patreon"{% if site.support_title %} value="{{ site.support_title }}"{% endif %}>
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_admin_email">{% trans "Admin email:" %}</label>
|
||||
{{ site_form.admin_email }}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_footer_item">{% trans "Additional info:" %}</label>
|
||||
{{ site_form.footer_item }}
|
||||
</div>
|
||||
|
@ -79,15 +79,19 @@
|
|||
|
||||
<section class="block" id="registration">
|
||||
<h2 class="title is-4">{% trans "Registration" %}</h2>
|
||||
<div class="control">
|
||||
<label class="label" for="id_allow_registration">{% trans "Allow registration:" %}
|
||||
{{ site_form.allow_registration }}
|
||||
<div class="field">
|
||||
<label class="label" for="id_allow_registration">
|
||||
{{ site_form.allow_registration }}
|
||||
{% trans "Allow registration" %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control">
|
||||
<label class="label" for="id_allow_invite_requests">{% trans "Allow invite requests:" %}
|
||||
{{ site_form.allow_invite_requests }}
|
||||
<div class="field">
|
||||
<label class="label" for="id_allow_invite_requests">
|
||||
{{ site_form.allow_invite_requests }}
|
||||
{% trans "Allow invite requests" %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
|
||||
{{ site_form.registration_closed_text }}
|
||||
</div>
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
||||
<input type="hidden" name="book" value="{{ book.id }}">
|
||||
<div class="field">
|
||||
<label class="label" tabindex="0" id="add-readthrough-focus">
|
||||
<label class="label" tabindex="0" id="add-readthrough-focus" for="id_start_date-{{ readthrough.id }}">
|
||||
{% trans "Started reading" %}
|
||||
<input type="date" name="start_date" class="input" id="id_start_date-{{ readthrough.id }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
|
||||
</label>
|
||||
<input type="date" name="start_date" class="input" id="id_start_date-{{ readthrough.id }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
|
||||
</div>
|
||||
{# Only show progress for editing existing readthroughs #}
|
||||
{% if readthrough.id and not readthrough.finish_date %}
|
||||
|
@ -26,8 +26,8 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<label class="label" for="id_finish_date-{{ readthrough.id }}">
|
||||
{% trans "Finished reading" %}
|
||||
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ readthrough.id }}" value="{{ readthrough.finish_date | date:"Y-m-d" }}">
|
||||
</label>
|
||||
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ readthrough.id }}" value="{{ readthrough.finish_date | date:"Y-m-d" }}">
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
{% block modal-form-open %}
|
||||
<form name="finish-reading" action="/finish-reading/{{ book.id }}" method="post">
|
||||
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post">
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
|
@ -15,16 +15,16 @@
|
|||
{% csrf_token %}
|
||||
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<label class="label" for="finish_id_start_date-{{ uuid }}">
|
||||
{% trans "Started reading" %}
|
||||
<input type="date" name="start_date" class="input" id="finish_id_start_date-{{ uuid }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
|
||||
</label>
|
||||
<input type="date" name="start_date" class="input" id="finish_id_start_date-{{ uuid }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<label class="label" for="id_finish_date-{{ uuid }}">
|
||||
{% trans "Finished reading" %}
|
||||
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ uuid }}" value="{% now "Y-m-d" %}">
|
||||
</label>
|
||||
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ uuid }}" value="{% now "Y-m-d" %}">
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
@ -38,7 +38,7 @@
|
|||
</label>
|
||||
{% include 'snippets/privacy_select.html' %}
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="column has-text-right">
|
||||
<button type="submit" class="button is-success">{% trans "Save" %}</button>
|
||||
{% trans "Cancel" as button_text %}
|
||||
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="finish-reading" controls_uid=uuid %}
|
||||
|
|
|
@ -7,16 +7,25 @@
|
|||
{% if dropdown %}<li role="menuitem" class="dropdown-item p-0">{% endif %}
|
||||
<div class="{% if not dropdown and active_shelf.shelf.identifier|next_shelf != shelf.identifier %}is-hidden{% endif %}">
|
||||
{% if shelf.identifier == 'reading' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
|
||||
|
||||
{% trans "Start reading" as button_text %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start-reading" controls_uid=button_uuid focus="modal-title-start-reading" disabled=is_current %}
|
||||
{% url 'reading-status' 'start' book.id as fallback_url %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start-reading" controls_uid=button_uuid focus="modal-title-start-reading" disabled=is_current fallback_url=fallback_url %}
|
||||
|
||||
{% endif %}{% elif shelf.identifier == 'read' and active_shelf.shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
|
||||
<button type="button" class="button {{ class }}" disabled><span>{% trans "Read" %}</span>
|
||||
{% endif %}{% elif shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
|
||||
|
||||
{% trans "Finish reading" as button_text %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish-reading" controls_uid=button_uuid focus="modal-title-finish-reading" disabled=is_current %}
|
||||
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish-reading" controls_uid=button_uuid focus="modal-title-finish-reading" disabled=is_current fallback_url=fallback_url %}
|
||||
|
||||
{% endif %}{% elif shelf.identifier == 'to-read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
|
||||
|
||||
{% trans "Want to read" as button_text %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want-to-read" controls_uid=button_uuid focus="modal-title-want-to-read" disabled=is_current %}
|
||||
{% url 'reading-status' 'want' book.id as fallback_url %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want-to-read" controls_uid=button_uuid focus="modal-title-want-to-read" disabled=is_current fallback_url=fallback_url %}
|
||||
|
||||
{% endif %}{% elif shelf.editable %}
|
||||
<form name="shelve" action="/shelve/" method="post">
|
||||
{% csrf_token %}
|
||||
|
@ -44,7 +53,9 @@
|
|||
{% csrf_token %}
|
||||
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
|
||||
<input type="hidden" name="shelf" value="{{ active_shelf.shelf.id }}">
|
||||
<button class="button is-fullwidth is-small{% if dropdown %} is-radiusless{% endif %} is-danger is-light" type="submit">{% blocktrans with name=active_shelf.shelf.name %}Remove from {{ name }}{% endblocktrans %}</button>
|
||||
<button class="button is-fullwidth is-small{% if dropdown %} is-radiusless{% endif %} is-danger is-light" type="submit">
|
||||
{% blocktrans with name=active_shelf.shelf.name %}Remove from {{ name }}{% endblocktrans %}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
|
|
@ -2,21 +2,23 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block modal-title %}
|
||||
{% blocktrans with book_title=book.title %}Start "<em>{{ book_title }}</em>"{% endblocktrans %}
|
||||
{% blocktrans trimmed with book_title=book.title %}
|
||||
Start "<em>{{ book_title }}</em>"
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-form-open %}
|
||||
<form name="start-reading" action="/start-reading/{{ book.id }}" method="post">
|
||||
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post">
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<section class="modal-card-body">
|
||||
{% csrf_token %}
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<label class="label" for="start_id_start_date-{{ uuid }}">
|
||||
{% trans "Started reading" %}
|
||||
<input type="date" name="start_date" class="input" id="start_id_start_date-{{ uuid }}" value="{% now "Y-m-d" %}">
|
||||
</label>
|
||||
<input type="date" name="start_date" class="input" id="start_id_start_date-{{ uuid }}" value="{% now "Y-m-d" %}">
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
@ -30,7 +32,7 @@
|
|||
</label>
|
||||
{% include 'snippets/privacy_select.html' %}
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="column has-text-right">
|
||||
<button class="button is-success" type="submit">{% trans "Save" %}</button>
|
||||
{% trans "Cancel" as button_text %}
|
||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="start-reading" controls_uid=uuid %}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block modal-form-open %}
|
||||
<form name="shelve" action="/shelve/" method="post">
|
||||
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
|
||||
<input type="hidden" name="shelf" value="to-read">
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
{% if fallback_url %}
|
||||
<form name="fallback-form-{{ controls_uuid}}" method="GET" action="{{ fallback_url }}">
|
||||
{% endif %}
|
||||
<button
|
||||
type="button"
|
||||
{% if not fallback_url %}
|
||||
type="button"
|
||||
{% else %}
|
||||
type="submit"
|
||||
{% endif %}
|
||||
class="{% if not nonbutton %}button {% endif %}{{ class }}{% if button_type %} {{ button_type }}{% endif %}"
|
||||
data-controls="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}"
|
||||
{% if focus %}data-focus-target="{{ focus }}{% if controls_uid %}-{{ controls_uid }}{% endif %}"{% endif %}
|
||||
|
@ -20,3 +27,6 @@
|
|||
<span>{{ text }}</span>
|
||||
{% endif %}
|
||||
</button>
|
||||
{% if fallback_url %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<div class="column is-narrow">
|
||||
<a href="{% url 'prefs-profile' %}">
|
||||
<span class="icon icon-pencil" title="Edit profile" aria-hidden="true"></span>
|
||||
<span>{% trans "Edit profile" %}</span>
|
||||
<span class="is-hidden-mobile">{% trans "Edit profile" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -26,7 +26,7 @@
|
|||
<h2 class="title">
|
||||
{% include 'user/shelf/books_header.html' %}
|
||||
</h2>
|
||||
<div class="columns">
|
||||
<div class="columns is-mobile scroll-x">
|
||||
{% for shelf in shelves %}
|
||||
<div class="column is-narrow">
|
||||
<h3>{{ shelf.name }}
|
||||
|
@ -60,7 +60,7 @@
|
|||
<div class="column is-narrow">
|
||||
<a target="_blank" href="{{ user.local_path }}/rss">
|
||||
<span class="icon icon-rss" aria-hidden="true"></span>
|
||||
<span>{% trans "RSS feed" %}</span>
|
||||
<span class="is-hidden-mobile">{% trans "RSS feed" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block filter %}
|
||||
<label class="label" for="id_server">{% trans "Server name" %}</label>
|
||||
<label class="label" for="id_server">{% trans "Instance name" %}</label>
|
||||
<input type="text" class="input" name="server" value="{{ request.GET.server|default:'' }}" id="id_server" placeholder="example.server.com">
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{% block header %}
|
||||
{% if server %}
|
||||
{% blocktrans with server_name=server.server_name %}Users: <small>{{ server_name }}</small>{% endblocktrans %}
|
||||
{% blocktrans with instance_name=server.server_name %}Users: <small>{{ instance_name }}</small>{% endblocktrans %}
|
||||
<a href="{% url 'settings-users' %}" class="help has-text-weight-normal">Clear filters</a>
|
||||
{% else %}
|
||||
{% trans "Users" %}
|
||||
|
@ -35,7 +35,7 @@
|
|||
{% include 'snippets/table-sort-header.html' with field="is_active" sort=sort text=text %}
|
||||
</th>
|
||||
<th>
|
||||
{% trans "Remote server" as text %}
|
||||
{% trans "Remote instance" as text %}
|
||||
{% include 'snippets/table-sort-header.html' with field="federated_server__server_name" sort=sort text=text %}
|
||||
</th>
|
||||
</tr>
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
{% load i18n %}
|
||||
<div class="block content">
|
||||
{% if not user.is_active and user.deactivation_reason == "self_deletion" %}
|
||||
<div class="notification is-danger">
|
||||
{% trans "Permanently deleted" %}
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>{% trans "Actions" %}</h3>
|
||||
|
||||
<div class="is-flex">
|
||||
<p class="mr-1">
|
||||
<a class="button" href="{% url 'direct-messages-user' user.username %}">{% trans "Send direct message" %}</a>
|
||||
|
@ -14,6 +20,7 @@
|
|||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if user.local %}
|
||||
<div>
|
||||
<form name="permission" method="post" action="{% url 'settings-user' user.id %}">
|
||||
|
@ -39,4 +46,6 @@
|
|||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{% load i18n %}
|
||||
{% load utilities %}
|
||||
|
||||
{% if widget.is_initial %}
|
||||
<p class="mb-1">
|
||||
{{ widget.initial_text }}:
|
||||
<a href="{{ widget.value.url }}">{{ widget.value|truncatepath:10 }}</a>
|
||||
</p>
|
||||
{% if not widget.required %}
|
||||
<p class="mb-1">
|
||||
<label class="has-text-weight-normal">
|
||||
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}>
|
||||
{{ widget.clear_checkbox_label }}
|
||||
</label>{% endif %}
|
||||
</p>
|
||||
<p class="mb-1">
|
||||
{{ widget.input_text }}:
|
||||
{% else %}
|
||||
<p class="mb-1">
|
||||
{% endif %}
|
||||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||
<span class="help file-cta is-hidden file-too-big">{% trans "File exceeds maximum size: 10MB" %}</span>
|
||||
</p>
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
""" template filters for really common utilities """
|
||||
import os
|
||||
from uuid import uuid4
|
||||
from django import template
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
@ -19,13 +21,16 @@ def get_user_identifier(user):
|
|||
|
||||
|
||||
@register.filter(name="book_title")
|
||||
def get_title(book):
|
||||
def get_title(book, too_short=5):
|
||||
"""display the subtitle if the title is short"""
|
||||
if not book:
|
||||
return ""
|
||||
title = book.title
|
||||
if len(title) < 6 and book.subtitle:
|
||||
title = "{:s}: {:s}".format(title, book.subtitle)
|
||||
if len(title) <= too_short and book.subtitle:
|
||||
title = _("%(title)s: %(subtitle)s") % {
|
||||
"title": title,
|
||||
"subtitle": book.subtitle,
|
||||
}
|
||||
return title
|
||||
|
||||
|
||||
|
@ -33,3 +38,15 @@ def get_title(book):
|
|||
def comparison_bool(str1, str2):
|
||||
"""idk why I need to write a tag for this, it reutrns a bool"""
|
||||
return str1 == str2
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
def truncatepath(value, arg):
|
||||
"""Truncate a path by removing all directories except the first and truncating ."""
|
||||
path = os.path.normpath(value.name)
|
||||
path_list = path.split(os.sep)
|
||||
try:
|
||||
length = int(arg)
|
||||
except ValueError: # invalid literal for int()
|
||||
return path_list[-1] # Fail silently.
|
||||
return "%s/…%s" % (path_list[0], path_list[-1][-length:])
|
||||
|
|
|
@ -16,6 +16,7 @@ from bookwyrm import activitypub, models, settings
|
|||
# pylint: disable=too-many-public-methods
|
||||
@patch("bookwyrm.models.Status.broadcast")
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
class Status(TestCase):
|
||||
"""lotta types of statuses"""
|
||||
|
||||
|
@ -393,7 +394,8 @@ class Status(TestCase):
|
|||
user=self.local_user, notification_type="GLORB"
|
||||
)
|
||||
|
||||
def test_create_broadcast(self, _, broadcast_mock):
|
||||
# pylint: disable=unused-argument
|
||||
def test_create_broadcast(self, one, two, broadcast_mock, *_):
|
||||
"""should send out two verions of a status on create"""
|
||||
models.Comment.objects.create(
|
||||
content="hi", user=self.local_user, book=self.book
|
||||
|
|
|
@ -16,6 +16,7 @@ from bookwyrm.templatetags import (
|
|||
|
||||
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
class TemplateTags(TestCase):
|
||||
"""lotta different things here"""
|
||||
|
||||
|
@ -40,29 +41,29 @@ class TemplateTags(TestCase):
|
|||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
self.book = models.Edition.objects.create(title="Test Book")
|
||||
|
||||
def test_get_user_rating(self, _):
|
||||
def test_get_user_rating(self, *_):
|
||||
"""get a user's most recent rating of a book"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
models.Review.objects.create(user=self.user, book=self.book, rating=3)
|
||||
self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 3)
|
||||
|
||||
def test_get_user_rating_doesnt_exist(self, _):
|
||||
def test_get_user_rating_doesnt_exist(self, *_):
|
||||
"""there is no rating available"""
|
||||
self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 0)
|
||||
|
||||
def test_get_user_identifer_local(self, _):
|
||||
def test_get_user_identifer_local(self, *_):
|
||||
"""fall back to the simplest uid available"""
|
||||
self.assertNotEqual(self.user.username, self.user.localname)
|
||||
self.assertEqual(utilities.get_user_identifier(self.user), "mouse")
|
||||
|
||||
def test_get_user_identifer_remote(self, _):
|
||||
def test_get_user_identifer_remote(self, *_):
|
||||
"""for a remote user, should be their full username"""
|
||||
self.assertEqual(
|
||||
utilities.get_user_identifier(self.remote_user), "rat@example.com"
|
||||
)
|
||||
|
||||
def test_get_replies(self, _):
|
||||
def test_get_replies(self, *_):
|
||||
"""direct replies to a status"""
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
with patch(
|
||||
|
@ -93,7 +94,7 @@ class TemplateTags(TestCase):
|
|||
self.assertTrue(second_child in replies)
|
||||
self.assertFalse(third_child in replies)
|
||||
|
||||
def test_get_parent(self, _):
|
||||
def test_get_parent(self, *_):
|
||||
"""get the reply parent of a status"""
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
with patch(
|
||||
|
@ -110,7 +111,7 @@ class TemplateTags(TestCase):
|
|||
self.assertEqual(result, parent)
|
||||
self.assertIsInstance(result, models.Review)
|
||||
|
||||
def test_get_user_liked(self, _):
|
||||
def test_get_user_liked(self, *_):
|
||||
"""did a user like a status"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
status = models.Review.objects.create(user=self.remote_user, book=self.book)
|
||||
|
@ -120,7 +121,7 @@ class TemplateTags(TestCase):
|
|||
models.Favorite.objects.create(user=self.user, status=status)
|
||||
self.assertTrue(interaction.get_user_liked(self.user, status))
|
||||
|
||||
def test_get_user_boosted(self, _):
|
||||
def test_get_user_boosted(self, *_):
|
||||
"""did a user boost a status"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
status = models.Review.objects.create(user=self.remote_user, book=self.book)
|
||||
|
@ -130,7 +131,7 @@ class TemplateTags(TestCase):
|
|||
models.Boost.objects.create(user=self.user, boosted_status=status)
|
||||
self.assertTrue(interaction.get_user_boosted(self.user, status))
|
||||
|
||||
def test_get_boosted(self, _):
|
||||
def test_get_boosted(self, *_):
|
||||
"""load a boosted status"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
|
@ -144,7 +145,7 @@ class TemplateTags(TestCase):
|
|||
self.assertIsInstance(boosted, models.Review)
|
||||
self.assertEqual(boosted, status)
|
||||
|
||||
def test_get_book_description(self, _):
|
||||
def test_get_book_description(self, *_):
|
||||
"""grab it from the edition or the parent"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
work = models.Work.objects.create(title="Test Work")
|
||||
|
@ -161,12 +162,12 @@ class TemplateTags(TestCase):
|
|||
self.book.save()
|
||||
self.assertEqual(bookwyrm_tags.get_book_description(self.book), "hello")
|
||||
|
||||
def test_get_uuid(self, _):
|
||||
def test_get_uuid(self, *_):
|
||||
"""uuid functionality"""
|
||||
uuid = utilities.get_uuid("hi")
|
||||
self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
|
||||
|
||||
def test_get_markdown(self, _):
|
||||
def test_get_markdown(self, *_):
|
||||
"""mardown format data"""
|
||||
result = markdown.get_markdown("_hi_")
|
||||
self.assertEqual(result, "<p><em>hi</em></p>")
|
||||
|
@ -174,13 +175,13 @@ class TemplateTags(TestCase):
|
|||
result = markdown.get_markdown("<marquee>_hi_</marquee>")
|
||||
self.assertEqual(result, "<p><em>hi</em></p>")
|
||||
|
||||
def test_get_mentions(self, _):
|
||||
def test_get_mentions(self, *_):
|
||||
"""list of people mentioned"""
|
||||
status = models.Status.objects.create(content="hi", user=self.remote_user)
|
||||
result = status_display.get_mentions(status, self.user)
|
||||
self.assertEqual(result, "@rat@example.com ")
|
||||
|
||||
def test_related_status(self, _):
|
||||
def test_related_status(self, *_):
|
||||
"""gets the subclass model for a notification status"""
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
status = models.Status.objects.create(content="hi", user=self.user)
|
||||
|
|
|
@ -54,7 +54,8 @@ class InboxActivities(TestCase):
|
|||
models.SiteSettings.objects.create()
|
||||
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
def test_boost(self, redis_mock):
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
def test_boost(self, redis_mock, _):
|
||||
"""boost a status"""
|
||||
self.assertEqual(models.Notification.objects.count(), 0)
|
||||
activity = {
|
||||
|
@ -84,7 +85,8 @@ class InboxActivities(TestCase):
|
|||
|
||||
@responses.activate
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
def test_boost_remote_status(self, redis_mock):
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
def test_boost_remote_status(self, redis_mock, _):
|
||||
"""boost a status from a remote server"""
|
||||
with patch("bookwyrm.preview_images.generate_edition_preview_image_task.delay"):
|
||||
work = models.Work.objects.create(title="work title")
|
||||
|
@ -157,12 +159,13 @@ class InboxActivities(TestCase):
|
|||
views.inbox.activity_task(activity)
|
||||
self.assertEqual(models.Boost.objects.count(), 0)
|
||||
|
||||
def test_unboost(self):
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
def test_unboost(self, *_):
|
||||
"""undo a boost"""
|
||||
with patch("bookwyrm.activitystreams.ActivityStream.add_status"):
|
||||
boost = models.Boost.objects.create(
|
||||
boosted_status=self.status, user=self.remote_user
|
||||
)
|
||||
boost = models.Boost.objects.create(
|
||||
boosted_status=self.status, user=self.remote_user
|
||||
)
|
||||
activity = {
|
||||
"type": "Undo",
|
||||
"actor": "hi",
|
||||
|
@ -179,11 +182,7 @@ class InboxActivities(TestCase):
|
|||
"published": "Mon, 25 May 2020 19:31:20 GMT",
|
||||
},
|
||||
}
|
||||
with patch(
|
||||
"bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores"
|
||||
) as redis_mock:
|
||||
views.inbox.activity_task(activity)
|
||||
self.assertTrue(redis_mock.called)
|
||||
views.inbox.activity_task(activity)
|
||||
self.assertFalse(models.Boost.objects.exists())
|
||||
|
||||
def test_unboost_unknown_boost(self):
|
||||
|
|
150
bookwyrm/tests/views/test_edit_user.py
Normal file
150
bookwyrm/tests/views/test_edit_user.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
""" test for app action functionality """
|
||||
import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
from PIL import Image
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import forms, models, views
|
||||
|
||||
|
||||
class EditUserViews(TestCase):
|
||||
"""view user and edit profile"""
|
||||
|
||||
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.mouse",
|
||||
"password",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
)
|
||||
self.rat = models.User.objects.create_user(
|
||||
"rat@local.com", "rat@rat.rat", "password", local=True, localname="rat"
|
||||
)
|
||||
self.book = models.Edition.objects.create(title="test")
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
models.ShelfBook.objects.create(
|
||||
book=self.book,
|
||||
user=self.local_user,
|
||||
shelf=self.local_user.shelf_set.first(),
|
||||
)
|
||||
|
||||
models.SiteSettings.objects.create()
|
||||
self.anonymous_user = AnonymousUser
|
||||
self.anonymous_user.is_authenticated = False
|
||||
|
||||
def test_edit_user_page(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.EditUser.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_edit_user(self):
|
||||
"""use a form to update a user"""
|
||||
view = views.EditUser.as_view()
|
||||
form = forms.EditUserForm(instance=self.local_user)
|
||||
form.data["name"] = "New Name"
|
||||
form.data["email"] = "wow@email.com"
|
||||
form.data["preferred_timezone"] = "UTC"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
self.assertIsNone(self.local_user.name)
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
self.assertEqual(self.local_user.name, "New Name")
|
||||
self.assertEqual(self.local_user.email, "wow@email.com")
|
||||
|
||||
def test_edit_user_avatar(self):
|
||||
"""use a form to update a user"""
|
||||
view = views.EditUser.as_view()
|
||||
form = forms.EditUserForm(instance=self.local_user)
|
||||
form.data["name"] = "New Name"
|
||||
form.data["email"] = "wow@email.com"
|
||||
form.data["preferred_timezone"] = "UTC"
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
)
|
||||
form.data["avatar"] = SimpleUploadedFile(
|
||||
image_file, open(image_file, "rb").read(), content_type="image/jpeg"
|
||||
)
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
self.assertEqual(self.local_user.name, "New Name")
|
||||
self.assertEqual(self.local_user.email, "wow@email.com")
|
||||
self.assertIsNotNone(self.local_user.avatar)
|
||||
self.assertEqual(self.local_user.avatar.width, 120)
|
||||
self.assertEqual(self.local_user.avatar.height, 120)
|
||||
|
||||
def test_crop_avatar(self):
|
||||
"""reduce that image size"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
|
||||
result = views.edit_user.crop_avatar(image)
|
||||
self.assertIsInstance(result, ContentFile)
|
||||
image_result = Image.open(result)
|
||||
self.assertEqual(image_result.size, (120, 120))
|
||||
|
||||
def test_delete_user_page(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.DeleteUser.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_delete_user(self):
|
||||
"""use a form to update a user"""
|
||||
view = views.DeleteUser.as_view()
|
||||
form = forms.DeleteUserForm()
|
||||
form.data["password"] = "password"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
middleware = SessionMiddleware()
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
|
||||
self.assertIsNone(self.local_user.name)
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
activity = json.loads(delay_mock.call_args[0][1])
|
||||
self.assertEqual(activity["type"], "Delete")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(
|
||||
activity["cc"][0], "https://www.w3.org/ns/activitystreams#Public"
|
||||
)
|
||||
|
||||
self.local_user.refresh_from_db()
|
||||
self.assertFalse(self.local_user.is_active)
|
||||
self.assertEqual(self.local_user.deactivation_reason, "self_deletion")
|
|
@ -8,6 +8,7 @@ from bookwyrm import models, views
|
|||
|
||||
|
||||
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores")
|
||||
class InteractionViews(TestCase):
|
||||
"""viewing and creating statuses"""
|
||||
|
||||
|
@ -42,7 +43,7 @@ class InteractionViews(TestCase):
|
|||
parent_work=work,
|
||||
)
|
||||
|
||||
def test_favorite(self, _):
|
||||
def test_favorite(self, *_):
|
||||
"""create and broadcast faving a status"""
|
||||
view = views.Favorite.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -60,7 +61,7 @@ class InteractionViews(TestCase):
|
|||
self.assertEqual(notification.user, self.local_user)
|
||||
self.assertEqual(notification.related_user, self.remote_user)
|
||||
|
||||
def test_unfavorite(self, _):
|
||||
def test_unfavorite(self, *_):
|
||||
"""unfav a status"""
|
||||
view = views.Unfavorite.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -77,7 +78,7 @@ class InteractionViews(TestCase):
|
|||
self.assertEqual(models.Favorite.objects.count(), 0)
|
||||
self.assertEqual(models.Notification.objects.count(), 0)
|
||||
|
||||
def test_boost(self, _):
|
||||
def test_boost(self, *_):
|
||||
"""boost a status"""
|
||||
view = views.Boost.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -99,7 +100,7 @@ class InteractionViews(TestCase):
|
|||
self.assertEqual(notification.related_user, self.remote_user)
|
||||
self.assertEqual(notification.related_status, status)
|
||||
|
||||
def test_self_boost(self, _):
|
||||
def test_self_boost(self, *_):
|
||||
"""boost your own status"""
|
||||
view = views.Boost.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -123,7 +124,7 @@ class InteractionViews(TestCase):
|
|||
|
||||
self.assertFalse(models.Notification.objects.exists())
|
||||
|
||||
def test_boost_unlisted(self, _):
|
||||
def test_boost_unlisted(self, *_):
|
||||
"""boost a status"""
|
||||
view = views.Boost.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -138,7 +139,7 @@ class InteractionViews(TestCase):
|
|||
boost = models.Boost.objects.get()
|
||||
self.assertEqual(boost.privacy, "unlisted")
|
||||
|
||||
def test_boost_private(self, _):
|
||||
def test_boost_private(self, *_):
|
||||
"""boost a status"""
|
||||
view = views.Boost.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -151,7 +152,7 @@ class InteractionViews(TestCase):
|
|||
view(request, status.id)
|
||||
self.assertFalse(models.Boost.objects.exists())
|
||||
|
||||
def test_boost_twice(self, _):
|
||||
def test_boost_twice(self, *_):
|
||||
"""boost a status"""
|
||||
view = views.Boost.as_view()
|
||||
request = self.factory.post("")
|
||||
|
@ -163,13 +164,17 @@ class InteractionViews(TestCase):
|
|||
view(request, status.id)
|
||||
self.assertEqual(models.Boost.objects.count(), 1)
|
||||
|
||||
def test_unboost(self, _):
|
||||
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
|
||||
def test_unboost(self, *_):
|
||||
"""undo a boost"""
|
||||
view = views.Unboost.as_view()
|
||||
request = self.factory.post("")
|
||||
request.user = self.remote_user
|
||||
with patch("bookwyrm.activitystreams.ActivityStream.add_status"):
|
||||
status = models.Status.objects.create(user=self.local_user, content="hi")
|
||||
status = models.Status.objects.create(user=self.local_user, content="hi")
|
||||
|
||||
with patch(
|
||||
"bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores"
|
||||
):
|
||||
views.Boost.as_view()(request, status.id)
|
||||
|
||||
self.assertEqual(models.Boost.objects.count(), 1)
|
||||
|
|
|
@ -58,7 +58,7 @@ class ReadingViews(TestCase):
|
|||
)
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
views.start_reading(request, self.book.id)
|
||||
views.ReadingStatus.as_view()(request, "start", self.book.id)
|
||||
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
||||
|
@ -88,7 +88,7 @@ class ReadingViews(TestCase):
|
|||
request = self.factory.post("")
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
views.start_reading(request, self.book.id)
|
||||
views.ReadingStatus.as_view()(request, "start", self.book.id)
|
||||
|
||||
self.assertFalse(to_read_shelf.books.exists())
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
@ -114,7 +114,7 @@ class ReadingViews(TestCase):
|
|||
request.user = self.local_user
|
||||
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
views.finish_reading(request, self.book.id)
|
||||
views.ReadingStatus.as_view()(request, "finish", self.book.id)
|
||||
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class ReadThrough(TestCase):
|
|||
self.assertEqual(self.edition.readthrough_set.count(), 0)
|
||||
|
||||
self.client.post(
|
||||
"/start-reading/{}".format(self.edition.id),
|
||||
"/reading-status/start/{}".format(self.edition.id),
|
||||
{
|
||||
"start_date": "2020-11-27",
|
||||
},
|
||||
|
@ -56,10 +56,9 @@ class ReadThrough(TestCase):
|
|||
self.assertEqual(self.edition.readthrough_set.count(), 0)
|
||||
|
||||
self.client.post(
|
||||
"/start-reading/{}".format(self.edition.id),
|
||||
"/reading-status/start/{}".format(self.edition.id),
|
||||
{
|
||||
"start_date": "2020-11-27",
|
||||
"progress": 50,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -68,15 +67,8 @@ class ReadThrough(TestCase):
|
|||
self.assertEqual(
|
||||
readthroughs[0].start_date, datetime(2020, 11, 27, tzinfo=timezone.utc)
|
||||
)
|
||||
self.assertEqual(readthroughs[0].progress, 50)
|
||||
self.assertEqual(readthroughs[0].finish_date, None)
|
||||
|
||||
progress_updates = readthroughs[0].progressupdate_set.all()
|
||||
self.assertEqual(len(progress_updates), 1)
|
||||
self.assertEqual(progress_updates[0].mode, models.ProgressMode.PAGE)
|
||||
self.assertEqual(progress_updates[0].progress, 50)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
|
||||
# Update progress
|
||||
self.client.post(
|
||||
"/edit-readthrough",
|
||||
|
@ -89,9 +81,9 @@ class ReadThrough(TestCase):
|
|||
progress_updates = (
|
||||
readthroughs[0].progressupdate_set.order_by("updated_date").all()
|
||||
)
|
||||
self.assertEqual(len(progress_updates), 2)
|
||||
self.assertEqual(progress_updates[1].mode, models.ProgressMode.PAGE)
|
||||
self.assertEqual(progress_updates[1].progress, 100)
|
||||
self.assertEqual(len(progress_updates), 1)
|
||||
self.assertEqual(progress_updates[0].mode, models.ProgressMode.PAGE)
|
||||
self.assertEqual(progress_updates[0].progress, 100)
|
||||
|
||||
# Edit doesn't publish anything
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
""" test for app action functionality """
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
from PIL import Image
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http.response import Http404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import forms, models, views
|
||||
from bookwyrm import models, views
|
||||
from bookwyrm.activitypub import ActivitypubResponse
|
||||
|
||||
|
||||
|
@ -139,74 +135,4 @@ class UserViews(TestCase):
|
|||
with patch("bookwyrm.views.user.is_api_request") as is_api:
|
||||
is_api.return_value = False
|
||||
with self.assertRaises(Http404):
|
||||
view(request, "rat")
|
||||
|
||||
def test_edit_user_page(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.EditUser.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_edit_user(self):
|
||||
"""use a form to update a user"""
|
||||
view = views.EditUser.as_view()
|
||||
form = forms.EditUserForm(instance=self.local_user)
|
||||
form.data["name"] = "New Name"
|
||||
form.data["email"] = "wow@email.com"
|
||||
form.data["preferred_timezone"] = "UTC"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
self.assertIsNone(self.local_user.name)
|
||||
with patch("bookwyrm.preview_images.generate_user_preview_image_task.delay"):
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
self.assertEqual(self.local_user.name, "New Name")
|
||||
self.assertEqual(self.local_user.email, "wow@email.com")
|
||||
|
||||
def test_edit_user_avatar(self):
|
||||
"""use a form to update a user"""
|
||||
view = views.EditUser.as_view()
|
||||
form = forms.EditUserForm(instance=self.local_user)
|
||||
form.data["name"] = "New Name"
|
||||
form.data["email"] = "wow@email.com"
|
||||
form.data["preferred_timezone"] = "UTC"
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
)
|
||||
form.data["avatar"] = SimpleUploadedFile(
|
||||
image_file, open(image_file, "rb").read(), content_type="image/jpeg"
|
||||
)
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
with patch("bookwyrm.preview_images.generate_user_preview_image_task.delay"):
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
self.assertEqual(self.local_user.name, "New Name")
|
||||
self.assertEqual(self.local_user.email, "wow@email.com")
|
||||
self.assertIsNotNone(self.local_user.avatar)
|
||||
self.assertEqual(self.local_user.avatar.width, 120)
|
||||
self.assertEqual(self.local_user.avatar.height, 120)
|
||||
|
||||
def test_crop_avatar(self):
|
||||
"""reduce that image size"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
|
||||
result = views.user.crop_avatar(image)
|
||||
self.assertIsInstance(result, ContentFile)
|
||||
image_result = Image.open(result)
|
||||
self.assertEqual(image_result.size, (120, 120))
|
||||
view(request, "rat")
|
|
@ -223,7 +223,7 @@ urlpatterns = [
|
|||
re_path(
|
||||
r"^list/(?P<list_id>\d+)/curate/?$", views.Curate.as_view(), name="list-curate"
|
||||
),
|
||||
# Uyser books
|
||||
# User books
|
||||
re_path(r"%s/books/?$" % user_path, views.Shelf.as_view(), name="user-shelves"),
|
||||
re_path(
|
||||
r"^%s/(helf|books)/(?P<shelf_identifier>[\w-]+)(.json)?/?$" % user_path,
|
||||
|
@ -253,6 +253,7 @@ urlpatterns = [
|
|||
views.ChangePassword.as_view(),
|
||||
name="prefs-password",
|
||||
),
|
||||
re_path(r"^preferences/delete/?$", views.DeleteUser.as_view(), name="prefs-delete"),
|
||||
re_path(r"^preferences/block/?$", views.Block.as_view(), name="prefs-block"),
|
||||
re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()),
|
||||
re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock),
|
||||
|
@ -315,8 +316,12 @@ urlpatterns = [
|
|||
re_path(r"^delete-readthrough/?$", views.delete_readthrough),
|
||||
re_path(r"^create-readthrough/?$", views.create_readthrough),
|
||||
re_path(r"^delete-progressupdate/?$", views.delete_progressupdate),
|
||||
re_path(r"^start-reading/(?P<book_id>\d+)/?$", views.start_reading),
|
||||
re_path(r"^finish-reading/(?P<book_id>\d+)/?$", views.finish_reading),
|
||||
# shelve actions
|
||||
re_path(
|
||||
r"^reading-status/(?P<status>want|start|finish)/(?P<book_id>\d+)/?$",
|
||||
views.ReadingStatus.as_view(),
|
||||
name="reading-status",
|
||||
),
|
||||
# following
|
||||
re_path(r"^follow/?$", views.follow, name="follow"),
|
||||
re_path(r"^unfollow/?$", views.unfollow, name="unfollow"),
|
||||
|
|
|
@ -6,6 +6,7 @@ from .block import Block, unblock
|
|||
from .books import Book, EditBook, ConfirmEditBook, Editions
|
||||
from .books import upload_cover, add_description, switch_edition, resolve_book
|
||||
from .directory import Directory
|
||||
from .edit_user import EditUser, DeleteUser
|
||||
from .federation import Federation, FederatedServer
|
||||
from .federation import AddFederatedServer, ImportServerBlocklist
|
||||
from .federation import block_server, unblock_server
|
||||
|
@ -24,8 +25,9 @@ from .landing import About, Home, Discover
|
|||
from .list import Lists, List, Curate, UserLists
|
||||
from .notifications import Notifications
|
||||
from .outbox import Outbox
|
||||
from .reading import edit_readthrough, create_readthrough, delete_readthrough
|
||||
from .reading import start_reading, finish_reading, delete_progressupdate
|
||||
from .reading import edit_readthrough, create_readthrough
|
||||
from .reading import delete_readthrough, delete_progressupdate
|
||||
from .reading import ReadingStatus
|
||||
from .reports import Report, Reports, make_report, resolve_report, suspend_user
|
||||
from .rss_feed import RssFeed
|
||||
from .password import PasswordResetRequest, PasswordReset, ChangePassword
|
||||
|
@ -36,6 +38,6 @@ from .shelf import shelve, unshelve
|
|||
from .site import Site
|
||||
from .status import CreateStatus, DeleteStatus, DeleteAndRedraft
|
||||
from .updates import get_notification_count, get_unread_status_count
|
||||
from .user import User, EditUser, Followers, Following
|
||||
from .user import User, Followers, Following
|
||||
from .user_admin import UserAdmin, UserAdminList
|
||||
from .wellknown import *
|
||||
|
|
113
bookwyrm/views/edit_user.py
Normal file
113
bookwyrm/views/edit_user.py
Normal file
|
@ -0,0 +1,113 @@
|
|||
""" edit or delete ones own account"""
|
||||
from io import BytesIO
|
||||
from uuid import uuid4
|
||||
from PIL import Image
|
||||
|
||||
from django.contrib.auth import logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.files.base import ContentFile
|
||||
from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import forms, models
|
||||
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
class EditUser(View):
|
||||
"""edit user view"""
|
||||
|
||||
def get(self, request):
|
||||
"""edit profile page for a user"""
|
||||
data = {
|
||||
"form": forms.EditUserForm(instance=request.user),
|
||||
"user": request.user,
|
||||
}
|
||||
return TemplateResponse(request, "preferences/edit_user.html", data)
|
||||
|
||||
def post(self, request):
|
||||
"""les get fancy with images"""
|
||||
form = forms.EditUserForm(request.POST, request.FILES, instance=request.user)
|
||||
if not form.is_valid():
|
||||
data = {"form": form, "user": request.user}
|
||||
return TemplateResponse(request, "preferences/edit_user.html", data)
|
||||
|
||||
user = save_user_form(form)
|
||||
|
||||
return redirect(user.local_path)
|
||||
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
class DeleteUser(View):
|
||||
"""delete user view"""
|
||||
|
||||
def get(self, request):
|
||||
"""delete page for a user"""
|
||||
data = {
|
||||
"form": forms.DeleteUserForm(),
|
||||
"user": request.user,
|
||||
}
|
||||
return TemplateResponse(request, "preferences/delete_user.html", data)
|
||||
|
||||
def post(self, request):
|
||||
"""les get fancy with images"""
|
||||
form = forms.DeleteUserForm(request.POST, instance=request.user)
|
||||
form.is_valid()
|
||||
# idk why but I couldn't get check_password to work on request.user
|
||||
user = models.User.objects.get(id=request.user.id)
|
||||
if form.is_valid() and user.check_password(form.cleaned_data["password"]):
|
||||
user.deactivation_reason = "self_deletion"
|
||||
user.delete()
|
||||
logout(request)
|
||||
return redirect("/")
|
||||
|
||||
form.errors["password"] = ["Invalid password"]
|
||||
data = {"form": form, "user": request.user}
|
||||
return TemplateResponse(request, "preferences/delete_user.html", data)
|
||||
|
||||
|
||||
def save_user_form(form):
|
||||
"""special handling for the user form"""
|
||||
user = form.save(commit=False)
|
||||
|
||||
if "avatar" in form.files:
|
||||
# crop and resize avatar upload
|
||||
image = Image.open(form.files["avatar"])
|
||||
image = crop_avatar(image)
|
||||
|
||||
# set the name to a hash
|
||||
extension = form.files["avatar"].name.split(".")[-1]
|
||||
filename = "%s.%s" % (uuid4(), extension)
|
||||
user.avatar.save(filename, image, save=False)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
def crop_avatar(image):
|
||||
"""reduce the size and make an avatar square"""
|
||||
target_size = 120
|
||||
width, height = image.size
|
||||
thumbnail_scale = (
|
||||
height / (width / target_size)
|
||||
if height > width
|
||||
else width / (height / target_size)
|
||||
)
|
||||
image.thumbnail([thumbnail_scale, thumbnail_scale])
|
||||
width, height = image.size
|
||||
|
||||
width_diff = width - target_size
|
||||
height_diff = height - target_size
|
||||
cropped = image.crop(
|
||||
(
|
||||
int(width_diff / 2),
|
||||
int(height_diff / 2),
|
||||
int(width - (width_diff / 2)),
|
||||
int(height - (height_diff / 2)),
|
||||
)
|
||||
)
|
||||
output = BytesIO()
|
||||
cropped.save(output, format=image.format)
|
||||
return ContentFile(output.getvalue())
|
|
@ -14,7 +14,7 @@ from django.views import View
|
|||
from bookwyrm import forms, models
|
||||
from bookwyrm.connectors import connector_manager
|
||||
from .helpers import get_suggested_users
|
||||
from .user import save_user_form
|
||||
from .edit_user import save_user_form
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
|
|
|
@ -78,13 +78,15 @@ class ImportStatus(View):
|
|||
|
||||
def get(self, request, job_id):
|
||||
"""status of an import job"""
|
||||
job = models.ImportJob.objects.get(id=job_id)
|
||||
job = get_object_or_404(models.ImportJob, id=job_id)
|
||||
if job.user != request.user:
|
||||
raise PermissionDenied
|
||||
|
||||
try:
|
||||
task = app.AsyncResult(job.task_id)
|
||||
except ValueError:
|
||||
task = None
|
||||
|
||||
items = job.items.order_by("index").all()
|
||||
failed_items = [i for i in items if i.fail_reason]
|
||||
items = [i for i in items if not i.fail_reason]
|
||||
|
|
|
@ -37,8 +37,12 @@ class ManageInvites(View):
|
|||
PAGE_LENGTH,
|
||||
)
|
||||
|
||||
page = paginated.get_page(request.GET.get("page"))
|
||||
data = {
|
||||
"invites": paginated.get_page(request.GET.get("page")),
|
||||
"invites": page,
|
||||
"page_range": paginated.get_elided_page_range(
|
||||
page.number, on_each_side=2, on_ends=1
|
||||
),
|
||||
"form": forms.CreateInviteForm(),
|
||||
}
|
||||
return TemplateResponse(request, "settings/manage_invites.html", data)
|
||||
|
@ -118,15 +122,16 @@ class ManageInviteRequests(View):
|
|||
reduce(operator.or_, (Q(**f) for f in filters))
|
||||
).distinct()
|
||||
|
||||
paginated = Paginator(
|
||||
requests,
|
||||
PAGE_LENGTH,
|
||||
)
|
||||
paginated = Paginator(requests, PAGE_LENGTH)
|
||||
|
||||
page = paginated.get_page(request.GET.get("page"))
|
||||
data = {
|
||||
"ignored": ignored,
|
||||
"count": paginated.count,
|
||||
"requests": paginated.get_page(request.GET.get("page")),
|
||||
"requests": page,
|
||||
"page_range": paginated.get_elided_page_range(
|
||||
page.number, on_each_side=2, on_ends=1
|
||||
),
|
||||
"sort": sort,
|
||||
}
|
||||
return TemplateResponse(request, "settings/manage_invite_requests.html", data)
|
||||
|
|
|
@ -7,95 +7,79 @@ from dateutil.parser import ParserError
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseBadRequest, HttpResponseNotFound
|
||||
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 models
|
||||
from .helpers import get_edition, handle_reading_status
|
||||
from .shelf import handle_unshelve
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
@login_required
|
||||
@require_POST
|
||||
def start_reading(request, book_id):
|
||||
"""begin reading a book"""
|
||||
book = get_edition(book_id)
|
||||
reading_shelf = models.Shelf.objects.filter(
|
||||
identifier=models.Shelf.READING, user=request.user
|
||||
).first()
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
# pylint: disable=no-self-use
|
||||
class ReadingStatus(View):
|
||||
"""consider reading a book"""
|
||||
|
||||
# create a readthrough
|
||||
readthrough = update_readthrough(request, book=book)
|
||||
if readthrough:
|
||||
readthrough.save()
|
||||
def get(self, request, status, book_id):
|
||||
"""modal page"""
|
||||
book = get_edition(book_id)
|
||||
template = {
|
||||
"want": "want.html",
|
||||
"start": "start.html",
|
||||
"finish": "finish.html",
|
||||
}.get(status)
|
||||
if not template:
|
||||
return HttpResponseNotFound()
|
||||
return TemplateResponse(request, f"reading_progress/{template}", {"book": book})
|
||||
|
||||
# create a progress update if we have a page
|
||||
readthrough.create_update()
|
||||
def post(self, request, status, book_id):
|
||||
"""desire a book"""
|
||||
identifier = {
|
||||
"want": models.Shelf.TO_READ,
|
||||
"start": models.Shelf.READING,
|
||||
"finish": models.Shelf.READ_FINISHED,
|
||||
}.get(status)
|
||||
if not identifier:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
current_status_shelfbook = (
|
||||
models.ShelfBook.objects.select_related("shelf")
|
||||
.filter(
|
||||
shelf__identifier__in=models.Shelf.READ_STATUS_IDENTIFIERS,
|
||||
user=request.user,
|
||||
book=book,
|
||||
desired_shelf = models.Shelf.objects.filter(
|
||||
identifier=identifier, user=request.user
|
||||
).first()
|
||||
|
||||
book = get_edition(book_id)
|
||||
|
||||
current_status_shelfbook = (
|
||||
models.ShelfBook.objects.select_related("shelf")
|
||||
.filter(
|
||||
shelf__identifier__in=models.Shelf.READ_STATUS_IDENTIFIERS,
|
||||
user=request.user,
|
||||
book=book,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if current_status_shelfbook is not None:
|
||||
if current_status_shelfbook.shelf.identifier != models.Shelf.READING:
|
||||
handle_unshelve(book, current_status_shelfbook.shelf)
|
||||
else: # It already was on the shelf
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
if current_status_shelfbook is not None:
|
||||
if current_status_shelfbook.shelf.identifier != desired_shelf.identifier:
|
||||
current_status_shelfbook.delete()
|
||||
else: # It already was on the shelf
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
||||
models.ShelfBook.objects.create(book=book, shelf=reading_shelf, user=request.user)
|
||||
|
||||
# post about it (if you want)
|
||||
if request.POST.get("post-status"):
|
||||
privacy = request.POST.get("privacy")
|
||||
handle_reading_status(request.user, reading_shelf, book, privacy)
|
||||
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def finish_reading(request, book_id):
|
||||
"""a user completed a book, yay"""
|
||||
book = get_edition(book_id)
|
||||
finished_read_shelf = models.Shelf.objects.filter(
|
||||
identifier=models.Shelf.READ_FINISHED, user=request.user
|
||||
).first()
|
||||
|
||||
# update or create a readthrough
|
||||
readthrough = update_readthrough(request, book=book)
|
||||
if readthrough:
|
||||
readthrough.save()
|
||||
|
||||
current_status_shelfbook = (
|
||||
models.ShelfBook.objects.select_related("shelf")
|
||||
.filter(
|
||||
shelf__identifier__in=models.Shelf.READ_STATUS_IDENTIFIERS,
|
||||
user=request.user,
|
||||
book=book,
|
||||
models.ShelfBook.objects.create(
|
||||
book=book, shelf=desired_shelf, user=request.user
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if current_status_shelfbook is not None:
|
||||
if current_status_shelfbook.shelf.identifier != models.Shelf.READ_FINISHED:
|
||||
handle_unshelve(book, current_status_shelfbook.shelf)
|
||||
else: # It already was on the shelf
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
||||
models.ShelfBook.objects.create(
|
||||
book=book, shelf=finished_read_shelf, user=request.user
|
||||
)
|
||||
if desired_shelf.identifier != models.Shelf.TO_READ:
|
||||
# update or create a readthrough
|
||||
readthrough = update_readthrough(request, book=book)
|
||||
if readthrough:
|
||||
readthrough.save()
|
||||
|
||||
# post about it (if you want)
|
||||
if request.POST.get("post-status"):
|
||||
privacy = request.POST.get("privacy")
|
||||
handle_reading_status(request.user, finished_read_shelf, book, privacy)
|
||||
# post about it (if you want)
|
||||
if request.POST.get("post-status"):
|
||||
privacy = request.POST.get("privacy")
|
||||
handle_reading_status(request.user, desired_shelf, book, privacy)
|
||||
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
||||
|
||||
@login_required
|
||||
|
|
|
@ -20,7 +20,7 @@ from .helpers import is_api_request, get_edition, get_user_from_username
|
|||
from .helpers import handle_reading_status, privacy_filter
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
# pylint: disable=no-self-use
|
||||
class Shelf(View):
|
||||
"""shelf page"""
|
||||
|
||||
|
@ -178,11 +178,6 @@ def shelve(request):
|
|||
models.ShelfBook.objects.create(
|
||||
book=book, shelf=desired_shelf, user=request.user
|
||||
)
|
||||
if desired_shelf.identifier == models.Shelf.TO_READ and request.POST.get(
|
||||
"post-status"
|
||||
):
|
||||
privacy = request.POST.get("privacy") or desired_shelf.privacy
|
||||
handle_reading_status(request.user, desired_shelf, book, privacy=privacy)
|
||||
else:
|
||||
try:
|
||||
models.ShelfBook.objects.create(
|
||||
|
@ -206,7 +201,6 @@ def unshelve(request):
|
|||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def handle_unshelve(book, shelf):
|
||||
"""unshelve a book"""
|
||||
row = models.ShelfBook.objects.get(book=book, shelf=shelf)
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
""" non-interactive pages """
|
||||
from io import BytesIO
|
||||
from uuid import uuid4
|
||||
from PIL import Image
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.paginator import Paginator
|
||||
from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import forms, models
|
||||
from bookwyrm import models
|
||||
from bookwyrm.activitypub import ActivitypubResponse
|
||||
from bookwyrm.settings import PAGE_LENGTH
|
||||
from .helpers import get_user_from_username, is_api_request
|
||||
from .helpers import privacy_filter
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
# pylint: disable=no-self-use
|
||||
class User(View):
|
||||
"""user profile page"""
|
||||
|
||||
|
@ -122,71 +114,3 @@ class Following(View):
|
|||
"follow_list": paginated.get_page(request.GET.get("page")),
|
||||
}
|
||||
return TemplateResponse(request, "user/relationships/following.html", data)
|
||||
|
||||
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
class EditUser(View):
|
||||
"""edit user view"""
|
||||
|
||||
def get(self, request):
|
||||
"""edit profile page for a user"""
|
||||
data = {
|
||||
"form": forms.EditUserForm(instance=request.user),
|
||||
"user": request.user,
|
||||
}
|
||||
return TemplateResponse(request, "preferences/edit_user.html", data)
|
||||
|
||||
def post(self, request):
|
||||
"""les get fancy with images"""
|
||||
form = forms.EditUserForm(request.POST, request.FILES, instance=request.user)
|
||||
if not form.is_valid():
|
||||
data = {"form": form, "user": request.user}
|
||||
return TemplateResponse(request, "preferences/edit_user.html", data)
|
||||
|
||||
user = save_user_form(form)
|
||||
|
||||
return redirect(user.local_path)
|
||||
|
||||
|
||||
def save_user_form(form):
|
||||
"""special handling for the user form"""
|
||||
user = form.save(commit=False)
|
||||
|
||||
if "avatar" in form.files:
|
||||
# crop and resize avatar upload
|
||||
image = Image.open(form.files["avatar"])
|
||||
image = crop_avatar(image)
|
||||
|
||||
# set the name to a hash
|
||||
extension = form.files["avatar"].name.split(".")[-1]
|
||||
filename = "%s.%s" % (uuid4(), extension)
|
||||
user.avatar.save(filename, image, save=False)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
def crop_avatar(image):
|
||||
"""reduce the size and make an avatar square"""
|
||||
target_size = 120
|
||||
width, height = image.size
|
||||
thumbnail_scale = (
|
||||
height / (width / target_size)
|
||||
if height > width
|
||||
else width / (height / target_size)
|
||||
)
|
||||
image.thumbnail([thumbnail_scale, thumbnail_scale])
|
||||
width, height = image.size
|
||||
|
||||
width_diff = width - target_size
|
||||
height_diff = height - target_size
|
||||
cropped = image.crop(
|
||||
(
|
||||
int(width_diff / 2),
|
||||
int(height_diff / 2),
|
||||
int(width - (width_diff / 2)),
|
||||
int(height - (height_diff / 2)),
|
||||
)
|
||||
)
|
||||
output = BytesIO()
|
||||
cropped.save(output, format=image.format)
|
||||
return ContentFile(output.getvalue())
|
||||
|
|
4
bw-dev
4
bw-dev
|
@ -84,13 +84,13 @@ case "$CMD" in
|
|||
runweb coverage run --source='.' --omit="*/test*,celerywyrm*,bookwyrm/migrations/*" manage.py test "$@"
|
||||
;;
|
||||
pytest)
|
||||
runweb pytest --no-cov-on-fail "$@"
|
||||
execweb pytest --no-cov-on-fail "$@"
|
||||
;;
|
||||
collectstatic)
|
||||
runweb python manage.py collectstatic --no-input
|
||||
;;
|
||||
makemessages)
|
||||
runweb django-admin makemessages --no-wrap --ignore=venv $@
|
||||
runweb django-admin makemessages --no-wrap --ignore=venv --all $@
|
||||
;;
|
||||
compilemessages)
|
||||
runweb django-admin compilemessages --ignore venv $@
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
""" bookwyrm settings and configuration """
|
||||
from bookwyrm.settings import *
|
||||
|
||||
CELERY_BROKER_URL = env("CELERY_BROKER")
|
||||
CELERY_BROKER_URL = CELERY_BROKER
|
||||
CELERY_ACCEPT_CONTENT = ["json"]
|
||||
CELERY_TASK_SERIALIZER = "json"
|
||||
CELERY_RESULT_BACKEND = "redis"
|
||||
FLOWER_PORT = env("FLOWER_PORT")
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS + [
|
||||
"celerywyrm",
|
||||
|
|
|
@ -74,10 +74,10 @@ services:
|
|||
restart: on-failure
|
||||
flower:
|
||||
build: .
|
||||
command: flower --port=${FLOWER_PORT}
|
||||
command: flower -A celerywyrm
|
||||
env_file: .env
|
||||
environment:
|
||||
- CELERY_BROKER_URL=${CELERY_BROKER}
|
||||
volumes:
|
||||
- .:/app
|
||||
networks:
|
||||
- main
|
||||
depends_on:
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 0.0.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-05-20 14:40-0700\n"
|
||||
"POT-Creation-Date: 2021-06-06 20:52+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"
|
||||
|
@ -62,12 +62,12 @@ msgid "Book Title"
|
|||
msgstr "Titel"
|
||||
|
||||
#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:84
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:115
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:85
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:116
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:101
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:107
|
||||
msgid "Sort By"
|
||||
msgstr ""
|
||||
|
||||
|
@ -83,41 +83,41 @@ msgstr "Zu lesen angefangen"
|
|||
msgid "Descending"
|
||||
msgstr "Zu lesen angefangen"
|
||||
|
||||
#: bookwyrm/models/fields.py:24
|
||||
#: bookwyrm/models/fields.py:25
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid remote_id"
|
||||
msgstr "%(value)s ist keine gültige remote_id"
|
||||
|
||||
#: bookwyrm/models/fields.py:33 bookwyrm/models/fields.py:42
|
||||
#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid username"
|
||||
msgstr "%(value)s ist kein gültiger Username"
|
||||
|
||||
#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:155
|
||||
#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152
|
||||
msgid "username"
|
||||
msgstr "Username"
|
||||
|
||||
#: bookwyrm/models/fields.py:170
|
||||
#: bookwyrm/models/fields.py:171
|
||||
msgid "A user with that username already exists."
|
||||
msgstr "Dieser Benutzename ist bereits vergeben."
|
||||
|
||||
#: bookwyrm/settings.py:155
|
||||
#: bookwyrm/settings.py:156
|
||||
msgid "English"
|
||||
msgstr "Englisch"
|
||||
|
||||
#: bookwyrm/settings.py:156
|
||||
#: bookwyrm/settings.py:157
|
||||
msgid "German"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: bookwyrm/settings.py:157
|
||||
#: bookwyrm/settings.py:158
|
||||
msgid "Spanish"
|
||||
msgstr "Spanisch"
|
||||
|
||||
#: bookwyrm/settings.py:158
|
||||
#: bookwyrm/settings.py:159
|
||||
msgid "French"
|
||||
msgstr "Französisch"
|
||||
|
||||
#: bookwyrm/settings.py:159
|
||||
#: bookwyrm/settings.py:160
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "Vereinfachtes Chinesisch"
|
||||
|
||||
|
@ -266,7 +266,7 @@ msgstr ""
|
|||
#: bookwyrm/templates/book/edit_book.html:263
|
||||
#: bookwyrm/templates/lists/form.html:42
|
||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||
#: bookwyrm/templates/settings/announcement_form.html:65
|
||||
#: bookwyrm/templates/settings/announcement_form.html:69
|
||||
#: bookwyrm/templates/settings/edit_server.html:68
|
||||
#: bookwyrm/templates/settings/federated_server.html:98
|
||||
#: bookwyrm/templates/settings/site.html:97
|
||||
|
@ -398,7 +398,7 @@ msgstr "Themen"
|
|||
msgid "Places"
|
||||
msgstr "Orte"
|
||||
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:64
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||
#: bookwyrm/templates/search/layout.html:25
|
||||
#: bookwyrm/templates/search/layout.html:50
|
||||
|
@ -414,7 +414,7 @@ msgstr "Zur Liste"
|
|||
|
||||
#: bookwyrm/templates/book/book.html:297
|
||||
#: bookwyrm/templates/book/cover_modal.html:31
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Add"
|
||||
msgstr "Hinzufügen"
|
||||
|
||||
|
@ -559,7 +559,7 @@ msgid "John Doe, Jane Smith"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/book/edit_book.html:183
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:77
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
msgid "Cover"
|
||||
msgstr ""
|
||||
|
||||
|
@ -688,7 +688,7 @@ msgstr "Föderiert"
|
|||
|
||||
#: bookwyrm/templates/directory/directory.html:4
|
||||
#: bookwyrm/templates/directory/directory.html:9
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
#: bookwyrm/templates/layout.html:64
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
|
@ -902,7 +902,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:87
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
msgid "Direct Messages"
|
||||
msgstr "Direktnachrichten"
|
||||
|
||||
|
@ -960,7 +960,6 @@ msgid "Updates"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/feed/feed_layout.html:10
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
#: bookwyrm/templates/user/shelf/books_header.html:3
|
||||
msgid "Your books"
|
||||
msgstr "Deine Bücher"
|
||||
|
@ -1022,7 +1021,7 @@ msgid "What are you reading?"
|
|||
msgstr "Zu lesen angefangen"
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:9
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
#: bookwyrm/templates/lists/list.html:135
|
||||
msgid "Search for a book"
|
||||
msgstr "Nach einem Buch suchen"
|
||||
|
||||
|
@ -1042,7 +1041,7 @@ msgstr ""
|
|||
#: bookwyrm/templates/get_started/users.html:18
|
||||
#: bookwyrm/templates/get_started/users.html:19
|
||||
#: bookwyrm/templates/layout.html:37 bookwyrm/templates/layout.html:38
|
||||
#: bookwyrm/templates/lists/list.html:124
|
||||
#: bookwyrm/templates/lists/list.html:139
|
||||
#: bookwyrm/templates/search/layout.html:4
|
||||
#: bookwyrm/templates/search/layout.html:9
|
||||
msgid "Search"
|
||||
|
@ -1061,7 +1060,7 @@ msgid "Popular on %(site_name)s"
|
|||
msgstr "Über %(site_name)s"
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:58
|
||||
#: bookwyrm/templates/lists/list.html:137
|
||||
#: bookwyrm/templates/lists/list.html:152
|
||||
msgid "No books found"
|
||||
msgstr "Keine Bücher gefunden"
|
||||
|
||||
|
@ -1184,7 +1183,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:97
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:40
|
||||
msgid "Import Books"
|
||||
msgstr "Bücher importieren"
|
||||
|
||||
|
@ -1271,14 +1270,14 @@ msgstr "Buch"
|
|||
|
||||
#: bookwyrm/templates/import_status.html:114
|
||||
#: bookwyrm/templates/snippets/create_status_form.html:13
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:98
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:99
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: bookwyrm/templates/import_status.html:117
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:101
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:102
|
||||
msgid "Author"
|
||||
msgstr "Autor*in"
|
||||
|
||||
|
@ -1320,15 +1319,21 @@ msgstr "Suche nach Buch oder Benutzer*in"
|
|||
msgid "Main navigation menu"
|
||||
msgstr "Navigationshauptmenü"
|
||||
|
||||
#: bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
msgid "Feed"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:102
|
||||
#: bookwyrm/templates/layout.html:87
|
||||
#, fuzzy
|
||||
#| msgid "Your books"
|
||||
msgid "Your Books"
|
||||
msgstr "Deine Bücher"
|
||||
|
||||
#: bookwyrm/templates/layout.html:97
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: bookwyrm/templates/layout.html:111
|
||||
#: bookwyrm/templates/layout.html:106
|
||||
#: bookwyrm/templates/settings/admin_layout.html:31
|
||||
#: bookwyrm/templates/settings/manage_invite_requests.html:15
|
||||
#: bookwyrm/templates/settings/manage_invites.html:3
|
||||
|
@ -1336,45 +1341,47 @@ msgstr "Einstellungen"
|
|||
msgid "Invites"
|
||||
msgstr "Einladungen"
|
||||
|
||||
#: bookwyrm/templates/layout.html:118
|
||||
#: bookwyrm/templates/layout.html:113
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:125
|
||||
#: bookwyrm/templates/layout.html:120
|
||||
msgid "Log out"
|
||||
msgstr "Abmelden"
|
||||
|
||||
#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
|
||||
#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129
|
||||
#: bookwyrm/templates/notifications.html:6
|
||||
#: bookwyrm/templates/notifications.html:11
|
||||
msgid "Notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
#: bookwyrm/templates/layout.html:154 bookwyrm/templates/layout.html:158
|
||||
#: 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:159
|
||||
#: bookwyrm/templates/layout.html:156
|
||||
msgid "password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:36
|
||||
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
|
||||
msgid "Forgot your password?"
|
||||
msgstr "Passwort vergessen?"
|
||||
|
||||
#: bookwyrm/templates/layout.html:163 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/login.html:33
|
||||
msgid "Log in"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: bookwyrm/templates/layout.html:171
|
||||
#: bookwyrm/templates/layout.html:168
|
||||
msgid "Join"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:206
|
||||
msgid "About this server"
|
||||
#, fuzzy
|
||||
#| msgid "About this server"
|
||||
msgid "About this instance"
|
||||
msgstr "Über diesen Server"
|
||||
|
||||
#: bookwyrm/templates/layout.html:210
|
||||
|
@ -1438,7 +1445,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:16
|
||||
msgid "Edit List"
|
||||
msgstr "Liste bearbeiten"
|
||||
|
||||
|
@ -1487,63 +1494,64 @@ msgstr "Alle können Bücher hinzufügen"
|
|||
msgid "This list is currently empty"
|
||||
msgstr "Diese Liste ist momentan leer"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:65
|
||||
#: bookwyrm/templates/lists/list.html:66
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
|
||||
msgid "Added by <a href=\"%(user_path)s\">%(username)s</a>"
|
||||
msgstr "Direktnachrichten mit <a href=\"%(path)s\">%(username)s</a>"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:77
|
||||
#, fuzzy
|
||||
#| msgid "Started"
|
||||
msgid "Set"
|
||||
msgstr "Gestartet"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:80
|
||||
#: bookwyrm/templates/lists/list.html:74
|
||||
#, fuzzy
|
||||
#| msgid "List curation:"
|
||||
msgid "List position"
|
||||
msgstr "Listenkuratierung:"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:86
|
||||
#: bookwyrm/templates/lists/list.html:81
|
||||
#, fuzzy
|
||||
#| msgid "Started"
|
||||
msgid "Set"
|
||||
msgstr "Gestartet"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:89
|
||||
#: bookwyrm/templates/snippets/shelf_selector.html:26
|
||||
msgid "Remove"
|
||||
msgstr "Entfernen"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:99 bookwyrm/templates/lists/list.html:111
|
||||
#: bookwyrm/templates/lists/list.html:103
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
#, fuzzy
|
||||
#| msgid "Your Lists"
|
||||
msgid "Sort List"
|
||||
msgstr "Deine Listen"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:105
|
||||
#: bookwyrm/templates/lists/list.html:113
|
||||
#, fuzzy
|
||||
#| msgid "List curation:"
|
||||
msgid "Direction"
|
||||
msgstr "Listenkuratierung:"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:127
|
||||
msgid "Add Books"
|
||||
msgstr "Bücher hinzufügen"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:129
|
||||
msgid "Suggest Books"
|
||||
msgstr "Bücher vorschlagen"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:125
|
||||
#: bookwyrm/templates/lists/list.html:140
|
||||
msgid "search"
|
||||
msgstr "suchen"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:131
|
||||
#: bookwyrm/templates/lists/list.html:146
|
||||
msgid "Clear search"
|
||||
msgstr "Suche leeren"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:136
|
||||
#: bookwyrm/templates/lists/list.html:151
|
||||
#, python-format
|
||||
msgid "No books found matching the query \"%(query)s\""
|
||||
msgstr "Keine passenden Bücher zu \"%(query)s\" gefunden"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Suggest"
|
||||
msgstr "Vorschlagen"
|
||||
|
||||
|
@ -1643,7 +1651,7 @@ msgstr "Lösen"
|
|||
#: bookwyrm/templates/moderation/reports.html:6
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Lists: %(username)s"
|
||||
msgid "Reports: %(server_name)s"
|
||||
msgid "Reports: %(instance_name)s"
|
||||
msgstr "Listen: %(username)s"
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:8
|
||||
|
@ -1657,7 +1665,7 @@ msgstr "Aktuelle Importe"
|
|||
#: bookwyrm/templates/moderation/reports.html:14
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Lists: %(username)s"
|
||||
msgid "Reports: <small>%(server_name)s</small>"
|
||||
msgid "Reports: <small>%(instance_name)s</small>"
|
||||
msgstr "Listen: %(username)s"
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:28
|
||||
|
@ -1863,6 +1871,26 @@ msgstr "Profil"
|
|||
msgid "Relationships"
|
||||
msgstr "Beziehungen"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr "bewertete"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr "kommentierte"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr "zitierte"
|
||||
|
||||
#: bookwyrm/templates/search/book.html:64
|
||||
#, fuzzy
|
||||
#| msgid "Show results from other catalogues"
|
||||
|
@ -1922,7 +1950,9 @@ msgstr "Nutzer*innen verwalten"
|
|||
#: bookwyrm/templates/settings/admin_layout.html:39
|
||||
#: bookwyrm/templates/settings/federation.html:3
|
||||
#: bookwyrm/templates/settings/federation.html:5
|
||||
msgid "Federated Servers"
|
||||
#, fuzzy
|
||||
#| msgid "Federated Servers"
|
||||
msgid "Federated Instances"
|
||||
msgstr "Föderierende Server"
|
||||
|
||||
#: bookwyrm/templates/settings/admin_layout.html:44
|
||||
|
@ -1976,6 +2006,7 @@ msgid "Back to list"
|
|||
msgstr "Zurück zu den Meldungen"
|
||||
|
||||
#: bookwyrm/templates/settings/announcement.html:11
|
||||
#: bookwyrm/templates/settings/announcement_form.html:6
|
||||
#, fuzzy
|
||||
#| msgid "Announcements"
|
||||
msgid "Edit Announcement"
|
||||
|
@ -2017,7 +2048,7 @@ msgstr "Geburtsdatum:"
|
|||
msgid "Active:"
|
||||
msgstr "Aktivität"
|
||||
|
||||
#: bookwyrm/templates/settings/announcement_form.html:5
|
||||
#: bookwyrm/templates/settings/announcement_form.html:8
|
||||
#: bookwyrm/templates/settings/announcements.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Announcements"
|
||||
|
@ -2076,15 +2107,15 @@ msgstr "Aktivität"
|
|||
#: bookwyrm/templates/settings/server_blocklist.html:3
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:20
|
||||
#, fuzzy
|
||||
#| msgid "Add cover"
|
||||
msgid "Add server"
|
||||
msgstr "Cover hinzufügen"
|
||||
#| msgid "Instance Name:"
|
||||
msgid "Add instance"
|
||||
msgstr "Instanzname"
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:7
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:7
|
||||
#, fuzzy
|
||||
#| msgid "Back to reports"
|
||||
msgid "Back to server list"
|
||||
msgid "Back to instance list"
|
||||
msgstr "Zurück zu den Meldungen"
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:16
|
||||
|
@ -2213,8 +2244,10 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/settings/federation.html:19
|
||||
#: bookwyrm/templates/user_admin/server_filter.html:5
|
||||
msgid "Server name"
|
||||
msgstr "Servername"
|
||||
#, fuzzy
|
||||
#| msgid "Instance Name:"
|
||||
msgid "Instance name"
|
||||
msgstr "Instanzname"
|
||||
|
||||
#: bookwyrm/templates/settings/federation.html:23
|
||||
#, fuzzy
|
||||
|
@ -2353,7 +2386,7 @@ msgid "Import Blocklist"
|
|||
msgstr "Bücher importieren"
|
||||
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:26
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:5
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
msgid "Success!"
|
||||
msgstr "Erfolg!"
|
||||
|
||||
|
@ -2446,15 +2479,15 @@ msgstr "Cover hinzufügen"
|
|||
msgid "<a href=\"%(path)s\">%(title)s</a> by "
|
||||
msgstr "<a href=\"%(path)s\">%(title)s</a> von "
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:9
|
||||
#: bookwyrm/templates/snippets/boost_button.html:10
|
||||
#: bookwyrm/templates/snippets/boost_button.html:20
|
||||
#: bookwyrm/templates/snippets/boost_button.html:21
|
||||
#, fuzzy
|
||||
#| msgid "boosted"
|
||||
msgid "Boost"
|
||||
msgstr "teilt"
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:16
|
||||
#: bookwyrm/templates/snippets/boost_button.html:17
|
||||
#: bookwyrm/templates/snippets/boost_button.html:33
|
||||
#: bookwyrm/templates/snippets/boost_button.html:34
|
||||
#, fuzzy
|
||||
#| msgid "Un-boost status"
|
||||
msgid "Un-boost"
|
||||
|
@ -2554,13 +2587,13 @@ msgstr "Diese Lesedaten löschen?"
|
|||
msgid "You are deleting this readthrough and its %(count)s associated progress updates."
|
||||
msgstr "Du löscht diesen Leseforschritt und %(count)s zugehörige Fortschrittsupdates."
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:9
|
||||
#: bookwyrm/templates/snippets/fav_button.html:11
|
||||
#: bookwyrm/templates/snippets/fav_button.html:10
|
||||
#: bookwyrm/templates/snippets/fav_button.html:12
|
||||
msgid "Like"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:17
|
||||
#: bookwyrm/templates/snippets/fav_button.html:18
|
||||
#: bookwyrm/templates/snippets/fav_button.html:19
|
||||
#, fuzzy
|
||||
#| msgid "Un-like status"
|
||||
msgid "Un-like"
|
||||
|
@ -2609,6 +2642,14 @@ msgstr "Annehmen"
|
|||
msgid "No rating"
|
||||
msgstr "Kein Rating"
|
||||
|
||||
#: bookwyrm/templates/snippets/form_rate_stars.html:44
|
||||
#: bookwyrm/templates/snippets/stars.html:7
|
||||
#, python-format
|
||||
msgid "%(rating)s star"
|
||||
msgid_plural "%(rating)s stars"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: bookwyrm/templates/snippets/generated_status/goal.html:1
|
||||
#, python-format
|
||||
msgid "set a goal to read %(counter)s book in %(year)s"
|
||||
|
@ -2664,17 +2705,17 @@ msgstr "Posten"
|
|||
msgid "Set goal"
|
||||
msgstr "Ziel setzen"
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:9
|
||||
#, python-format
|
||||
msgid "%(percent)s%% complete!"
|
||||
msgstr "%(percent)s%% komplett!"
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:10
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#, python-format
|
||||
msgid "You've read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr "Du hast <a href=\"%(path)s\">%(read_count)s von %(goal_count)s Büchern</a> gelesen."
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:14
|
||||
#, python-format
|
||||
msgid "%(username)s has read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr "%(username)s hat <a href=\"%(path)s\">%(read_count)s von %(goal_count)s Büchern</a> gelesen."
|
||||
|
@ -2787,26 +2828,6 @@ msgstr "Registrieren"
|
|||
msgid "Report"
|
||||
msgstr "Importieren"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr "bewertete"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr "kommentierte"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr "zitierte"
|
||||
|
||||
#: bookwyrm/templates/snippets/search_result_text.html:36
|
||||
msgid "Import book"
|
||||
msgstr "Buch importieren"
|
||||
|
@ -2989,7 +3010,7 @@ msgstr "Regal bearbeiten"
|
|||
msgid "Update shelf"
|
||||
msgstr "Regal aktualisieren"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:51
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56
|
||||
#, fuzzy
|
||||
#| msgid "books"
|
||||
msgid "All books"
|
||||
|
@ -2999,30 +3020,30 @@ msgstr "Bücher"
|
|||
msgid "Create shelf"
|
||||
msgstr "Regal erstellen"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:61
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:62
|
||||
msgid "Edit shelf"
|
||||
msgstr "Regal bearbeiten"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:104
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:105
|
||||
msgid "Shelved"
|
||||
msgstr "Ins Regal gestellt"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:108
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:109
|
||||
msgid "Started"
|
||||
msgstr "Gestartet"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:111
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:83
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:112
|
||||
msgid "Finished"
|
||||
msgstr "Abgeschlossen"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:137
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:138
|
||||
msgid "This shelf is empty."
|
||||
msgstr "Dieses Regal ist leer."
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:143
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:144
|
||||
msgid "Delete shelf"
|
||||
msgstr "Regal löschen"
|
||||
|
||||
|
@ -3084,9 +3105,10 @@ msgid "Back to users"
|
|||
msgstr "Zurück zu den Meldungen"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:7
|
||||
#, python-format
|
||||
msgid "Users: <small>%(server_name)s</small>"
|
||||
msgstr ""
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Lists: %(username)s"
|
||||
msgid "Users: <small>%(instance_name)s</small>"
|
||||
msgstr "Listen: %(username)s"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:22
|
||||
#: bookwyrm/templates/user_admin/username_filter.html:5
|
||||
|
@ -3107,9 +3129,9 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:38
|
||||
#, fuzzy
|
||||
#| msgid "Remove"
|
||||
msgid "Remote server"
|
||||
msgstr "Entfernen"
|
||||
#| msgid "Instance Name:"
|
||||
msgid "Remote instance"
|
||||
msgstr "Instanzname"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:47
|
||||
#, fuzzy
|
||||
|
@ -3158,6 +3180,10 @@ msgstr ""
|
|||
msgid "Access level:"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3
|
||||
msgid "File exceeds maximum size: 10MB"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/views/import_data.py:67
|
||||
#, fuzzy
|
||||
#| msgid "Email address:"
|
||||
|
@ -3175,6 +3201,27 @@ msgstr "Dieser Benutzename ist bereits vergeben."
|
|||
msgid "A password reset link sent to %s"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Lists: %(username)s"
|
||||
#~ msgid "Reports: <small>%(server_name)s</small>"
|
||||
#~ msgstr "Listen: %(username)s"
|
||||
|
||||
#~ msgid "Federated Servers"
|
||||
#~ msgstr "Föderierende Server"
|
||||
|
||||
#~ msgid "Server name"
|
||||
#~ msgstr "Servername"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Add cover"
|
||||
#~ msgid "Add server"
|
||||
#~ msgstr "Cover hinzufügen"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Remove"
|
||||
#~ msgid "Remote server"
|
||||
#~ msgstr "Entfernen"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Book"
|
||||
#~ msgid "BookWyrm\\"
|
||||
|
@ -3225,12 +3272,12 @@ msgstr ""
|
|||
#~ msgid "Enter a number."
|
||||
#~ msgstr "Seriennummer:"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "A user with that username already exists."
|
||||
#~ msgid "%(model_name)s with this %(field_labels)s already exists."
|
||||
#~ msgstr "Dieser Benutzename ist bereits vergeben."
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid remote_id"
|
||||
#~ msgid "Value %(value)r is not a valid choice."
|
||||
#~ msgstr "%(value)s ist keine gültige remote_id"
|
||||
|
@ -3240,7 +3287,7 @@ msgstr ""
|
|||
#~ msgid "This field cannot be null."
|
||||
#~ msgstr "Dieses Regal ist leer."
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "A user with that username already exists."
|
||||
#~ msgid "%(model_name)s with this %(field_label)s already exists."
|
||||
#~ msgstr "Dieser Benutzename ist bereits vergeben."
|
||||
|
@ -3250,7 +3297,7 @@ msgstr ""
|
|||
#~ msgid "Comma-separated integers"
|
||||
#~ msgstr "Keine aktiven Einladungen"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(value)s” value must be a decimal number."
|
||||
#~ msgstr "%(value)s ist kein gültiger Username"
|
||||
|
@ -3270,7 +3317,7 @@ msgstr ""
|
|||
#~ msgid "Email address"
|
||||
#~ msgstr "E-Mail Adresse"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(value)s” value must be a float."
|
||||
#~ msgstr "%(value)s ist kein gültiger Username"
|
||||
|
@ -3300,7 +3347,7 @@ msgstr ""
|
|||
#~ msgid "Positive small integer"
|
||||
#~ msgstr "Keine aktiven Einladungen"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(value)s” is not a valid UUID."
|
||||
#~ msgstr "%(value)s ist kein gültiger Username"
|
||||
|
@ -3315,12 +3362,12 @@ msgstr ""
|
|||
#~ msgid "One-to-one relationship"
|
||||
#~ msgstr "Beziehungen"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "Relationships"
|
||||
#~ msgid "%(from)s-%(to)s relationship"
|
||||
#~ msgstr "Beziehungen"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "Relationships"
|
||||
#~ msgid "%(from)s-%(to)s relationships"
|
||||
#~ msgstr "Beziehungen"
|
||||
|
@ -3375,7 +3422,7 @@ msgstr ""
|
|||
#~ msgid "Enter a valid UUID."
|
||||
#~ msgstr "E-Mail Adresse"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(pk)s” is not a valid value."
|
||||
#~ msgstr "%(value)s ist kein gültiger Username"
|
||||
|
@ -3439,12 +3486,12 @@ msgstr ""
|
|||
#~ msgid "This is not a valid IPv6 address."
|
||||
#~ msgstr "E-Mail Adresse"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "No books found matching the query \"%(query)s\""
|
||||
#~ msgid "No %(verbose_name)s found matching the query"
|
||||
#~ msgstr "Keine passenden Bücher zu \"%(query)s\" gefunden"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(path)s” does not exist"
|
||||
#~ msgstr "%(value)s ist kein gültiger Username"
|
||||
|
@ -3463,11 +3510,9 @@ msgstr ""
|
|||
#~ msgid "Matching Users"
|
||||
#~ msgstr "Passende Nutzer*innen"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Set a reading goal for %(year)s"
|
||||
#~ msgstr "Leseziel für %(year)s setzen"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "by %(author)s"
|
||||
#~ msgstr "von %(author)s"
|
||||
|
||||
|
@ -3477,17 +3522,17 @@ msgstr ""
|
|||
#~ msgid "Reactivate user"
|
||||
#~ msgstr "Nutzer:in reaktivieren"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| 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>"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| 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>"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| 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>"
|
||||
|
@ -3498,7 +3543,6 @@ msgstr ""
|
|||
#~ msgid "Add tag"
|
||||
#~ msgstr "Tag hinzufügen"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Books tagged \"%(tag.name)s\""
|
||||
#~ msgstr "Mit \"%(tag.name)s\" markierte Bücher"
|
||||
|
||||
|
@ -3507,7 +3551,7 @@ msgstr ""
|
|||
#~ msgid "Getting Started"
|
||||
#~ msgstr "Gestartet"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "No users found for \"%(query)s\""
|
||||
#~ msgid "No users were found for \"%(query)s\""
|
||||
#~ msgstr "Keine Nutzer*innen für \"%(query)s\" gefunden"
|
||||
|
@ -3515,7 +3559,7 @@ msgstr ""
|
|||
#~ msgid "Your lists"
|
||||
#~ msgstr "Deine Listen"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "See all %(size)s"
|
||||
#~ msgid "See all %(size)s lists"
|
||||
#~ msgstr "Alle %(size)s anzeigen"
|
||||
|
@ -3538,14 +3582,12 @@ msgstr ""
|
|||
#~ msgid "Your Shelves"
|
||||
#~ msgstr "Deine Regale"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "%(username)s: Shelves"
|
||||
#~ msgstr "%(username)s: Regale"
|
||||
|
||||
#~ msgid "Shelves"
|
||||
#~ msgstr "Regale"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "See all %(shelf_count)s shelves"
|
||||
#~ msgstr "Alle %(shelf_count)s Regale anzeigen"
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 0.0.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-05-20 14:40-0700\n"
|
||||
"POT-Creation-Date: 2021-06-06 20:52+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"
|
||||
|
@ -56,12 +56,12 @@ msgid "Book Title"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:84
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:115
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:85
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:116
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:101
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:107
|
||||
msgid "Sort By"
|
||||
msgstr ""
|
||||
|
||||
|
@ -73,41 +73,41 @@ msgstr ""
|
|||
msgid "Descending"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/models/fields.py:24
|
||||
#: bookwyrm/models/fields.py:25
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid remote_id"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/models/fields.py:33 bookwyrm/models/fields.py:42
|
||||
#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid username"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:155
|
||||
#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152
|
||||
msgid "username"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/models/fields.py:170
|
||||
#: bookwyrm/models/fields.py:171
|
||||
msgid "A user with that username already exists."
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/settings.py:155
|
||||
#: bookwyrm/settings.py:156
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/settings.py:156
|
||||
#: bookwyrm/settings.py:157
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/settings.py:157
|
||||
#: bookwyrm/settings.py:158
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/settings.py:158
|
||||
#: bookwyrm/settings.py:159
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/settings.py:159
|
||||
#: bookwyrm/settings.py:160
|
||||
msgid "Simplified Chinese"
|
||||
msgstr ""
|
||||
|
||||
|
@ -248,7 +248,7 @@ msgstr ""
|
|||
#: bookwyrm/templates/book/edit_book.html:263
|
||||
#: bookwyrm/templates/lists/form.html:42
|
||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||
#: bookwyrm/templates/settings/announcement_form.html:65
|
||||
#: bookwyrm/templates/settings/announcement_form.html:69
|
||||
#: bookwyrm/templates/settings/edit_server.html:68
|
||||
#: bookwyrm/templates/settings/federated_server.html:98
|
||||
#: bookwyrm/templates/settings/site.html:97
|
||||
|
@ -367,7 +367,7 @@ msgstr ""
|
|||
msgid "Places"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:64
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||
#: bookwyrm/templates/search/layout.html:25
|
||||
#: bookwyrm/templates/search/layout.html:50
|
||||
|
@ -381,7 +381,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/book/book.html:297
|
||||
#: bookwyrm/templates/book/cover_modal.html:31
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
|
@ -511,7 +511,7 @@ msgid "John Doe, Jane Smith"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/book/edit_book.html:183
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:77
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
msgid "Cover"
|
||||
msgstr ""
|
||||
|
||||
|
@ -630,7 +630,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/directory/directory.html:4
|
||||
#: bookwyrm/templates/directory/directory.html:9
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
#: bookwyrm/templates/layout.html:64
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
|
@ -831,7 +831,7 @@ msgid "Direct Messages with <a href=\"%(path)s\">%(username)s</a>"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/feed/direct_messages.html:10
|
||||
#: bookwyrm/templates/layout.html:87
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
msgid "Direct Messages"
|
||||
msgstr ""
|
||||
|
||||
|
@ -887,7 +887,6 @@ msgid "Updates"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/feed/feed_layout.html:10
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
#: bookwyrm/templates/user/shelf/books_header.html:3
|
||||
msgid "Your books"
|
||||
msgstr ""
|
||||
|
@ -942,7 +941,7 @@ msgid "What are you reading?"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:9
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
#: bookwyrm/templates/lists/list.html:135
|
||||
msgid "Search for a book"
|
||||
msgstr ""
|
||||
|
||||
|
@ -962,7 +961,7 @@ msgstr ""
|
|||
#: bookwyrm/templates/get_started/users.html:18
|
||||
#: bookwyrm/templates/get_started/users.html:19
|
||||
#: bookwyrm/templates/layout.html:37 bookwyrm/templates/layout.html:38
|
||||
#: bookwyrm/templates/lists/list.html:124
|
||||
#: bookwyrm/templates/lists/list.html:139
|
||||
#: bookwyrm/templates/search/layout.html:4
|
||||
#: bookwyrm/templates/search/layout.html:9
|
||||
msgid "Search"
|
||||
|
@ -978,7 +977,7 @@ msgid "Popular on %(site_name)s"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:58
|
||||
#: bookwyrm/templates/lists/list.html:137
|
||||
#: bookwyrm/templates/lists/list.html:152
|
||||
msgid "No books found"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1090,7 +1089,7 @@ msgid "%(username)s's %(year)s Books"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9
|
||||
#: bookwyrm/templates/layout.html:97
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:40
|
||||
msgid "Import Books"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1175,14 +1174,14 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/import_status.html:114
|
||||
#: bookwyrm/templates/snippets/create_status_form.html:13
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:98
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:99
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/import_status.html:117
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:101
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:102
|
||||
msgid "Author"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1224,15 +1223,19 @@ msgstr ""
|
|||
msgid "Main navigation menu"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
msgid "Feed"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:102
|
||||
#: bookwyrm/templates/layout.html:87
|
||||
msgid "Your Books"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:97
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:111
|
||||
#: bookwyrm/templates/layout.html:106
|
||||
#: bookwyrm/templates/settings/admin_layout.html:31
|
||||
#: bookwyrm/templates/settings/manage_invite_requests.html:15
|
||||
#: bookwyrm/templates/settings/manage_invites.html:3
|
||||
|
@ -1240,45 +1243,45 @@ msgstr ""
|
|||
msgid "Invites"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:118
|
||||
#: bookwyrm/templates/layout.html:113
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:125
|
||||
#: bookwyrm/templates/layout.html:120
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
|
||||
#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129
|
||||
#: bookwyrm/templates/notifications.html:6
|
||||
#: bookwyrm/templates/notifications.html:11
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:154 bookwyrm/templates/layout.html:158
|
||||
#: 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:159
|
||||
#: bookwyrm/templates/layout.html:156
|
||||
msgid "password"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:36
|
||||
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
|
||||
msgid "Forgot your password?"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:163 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/login.html:33
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:171
|
||||
#: bookwyrm/templates/layout.html:168
|
||||
msgid "Join"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:206
|
||||
msgid "About this server"
|
||||
msgid "About this instance"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/layout.html:210
|
||||
|
@ -1338,7 +1341,7 @@ msgid "Discard"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/edit_form.html:5
|
||||
#: bookwyrm/templates/lists/list_layout.html:17
|
||||
#: bookwyrm/templates/lists/list_layout.html:16
|
||||
msgid "Edit List"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1385,54 +1388,55 @@ msgstr ""
|
|||
msgid "This list is currently empty"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:65
|
||||
#: bookwyrm/templates/lists/list.html:66
|
||||
#, python-format
|
||||
msgid "Added by <a href=\"%(user_path)s\">%(username)s</a>"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:77
|
||||
msgid "Set"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:80
|
||||
#: bookwyrm/templates/lists/list.html:74
|
||||
msgid "List position"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:86
|
||||
#: bookwyrm/templates/lists/list.html:81
|
||||
msgid "Set"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:89
|
||||
#: bookwyrm/templates/snippets/shelf_selector.html:26
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:99 bookwyrm/templates/lists/list.html:111
|
||||
#: bookwyrm/templates/lists/list.html:103
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
msgid "Sort List"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:105
|
||||
#: bookwyrm/templates/lists/list.html:113
|
||||
msgid "Direction"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:127
|
||||
msgid "Add Books"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:129
|
||||
msgid "Suggest Books"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:125
|
||||
#: bookwyrm/templates/lists/list.html:140
|
||||
msgid "search"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:131
|
||||
#: bookwyrm/templates/lists/list.html:146
|
||||
msgid "Clear search"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:136
|
||||
#: bookwyrm/templates/lists/list.html:151
|
||||
#, python-format
|
||||
msgid "No books found matching the query \"%(query)s\""
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Suggest"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1523,7 +1527,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/moderation/reports.html:6
|
||||
#, python-format
|
||||
msgid "Reports: %(server_name)s"
|
||||
msgid "Reports: %(instance_name)s"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:8
|
||||
|
@ -1534,7 +1538,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/moderation/reports.html:14
|
||||
#, python-format
|
||||
msgid "Reports: <small>%(server_name)s</small>"
|
||||
msgid "Reports: <small>%(instance_name)s</small>"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:28
|
||||
|
@ -1733,6 +1737,26 @@ msgstr ""
|
|||
msgid "Relationships"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/search/book.html:64
|
||||
msgid "Load results from other catalogues"
|
||||
msgstr ""
|
||||
|
@ -1783,7 +1807,7 @@ msgstr ""
|
|||
#: bookwyrm/templates/settings/admin_layout.html:39
|
||||
#: bookwyrm/templates/settings/federation.html:3
|
||||
#: bookwyrm/templates/settings/federation.html:5
|
||||
msgid "Federated Servers"
|
||||
msgid "Federated Instances"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/admin_layout.html:44
|
||||
|
@ -1833,6 +1857,7 @@ msgid "Back to list"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/announcement.html:11
|
||||
#: bookwyrm/templates/settings/announcement_form.html:6
|
||||
msgid "Edit Announcement"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1866,7 +1891,7 @@ msgstr ""
|
|||
msgid "Active:"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/announcement_form.html:5
|
||||
#: bookwyrm/templates/settings/announcement_form.html:8
|
||||
#: bookwyrm/templates/settings/announcements.html:8
|
||||
msgid "Create Announcement"
|
||||
msgstr ""
|
||||
|
@ -1910,12 +1935,12 @@ msgstr ""
|
|||
#: bookwyrm/templates/settings/federation.html:10
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:3
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:20
|
||||
msgid "Add server"
|
||||
msgid "Add instance"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:7
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:7
|
||||
msgid "Back to server list"
|
||||
msgid "Back to instance list"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:16
|
||||
|
@ -2022,7 +2047,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/settings/federation.html:19
|
||||
#: bookwyrm/templates/user_admin/server_filter.html:5
|
||||
msgid "Server name"
|
||||
msgid "Instance name"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/federation.html:23
|
||||
|
@ -2144,7 +2169,7 @@ msgid "Import Blocklist"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:26
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:5
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
msgid "Success!"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2230,13 +2255,13 @@ msgstr ""
|
|||
msgid "<a href=\"%(path)s\">%(title)s</a> by "
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:9
|
||||
#: bookwyrm/templates/snippets/boost_button.html:10
|
||||
#: bookwyrm/templates/snippets/boost_button.html:20
|
||||
#: bookwyrm/templates/snippets/boost_button.html:21
|
||||
msgid "Boost"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:16
|
||||
#: bookwyrm/templates/snippets/boost_button.html:17
|
||||
#: bookwyrm/templates/snippets/boost_button.html:33
|
||||
#: bookwyrm/templates/snippets/boost_button.html:34
|
||||
msgid "Un-boost"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2326,13 +2351,13 @@ msgstr ""
|
|||
msgid "You are deleting this readthrough and its %(count)s associated progress updates."
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:9
|
||||
#: bookwyrm/templates/snippets/fav_button.html:11
|
||||
#: bookwyrm/templates/snippets/fav_button.html:10
|
||||
#: bookwyrm/templates/snippets/fav_button.html:12
|
||||
msgid "Like"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:17
|
||||
#: bookwyrm/templates/snippets/fav_button.html:18
|
||||
#: bookwyrm/templates/snippets/fav_button.html:19
|
||||
msgid "Un-like"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2373,6 +2398,14 @@ msgstr ""
|
|||
msgid "No rating"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/form_rate_stars.html:44
|
||||
#: bookwyrm/templates/snippets/stars.html:7
|
||||
#, python-format
|
||||
msgid "%(rating)s star"
|
||||
msgid_plural "%(rating)s stars"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: bookwyrm/templates/snippets/generated_status/goal.html:1
|
||||
#, python-format
|
||||
msgid "set a goal to read %(counter)s book in %(year)s"
|
||||
|
@ -2427,17 +2460,17 @@ msgstr ""
|
|||
msgid "Set goal"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:9
|
||||
#, python-format
|
||||
msgid "%(percent)s%% complete!"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:10
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#, python-format
|
||||
msgid "You've read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:14
|
||||
#, python-format
|
||||
msgid "%(username)s has read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr ""
|
||||
|
@ -2546,26 +2579,6 @@ msgstr ""
|
|||
msgid "Report"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/search_result_text.html:36
|
||||
msgid "Import book"
|
||||
msgstr ""
|
||||
|
@ -2735,7 +2748,7 @@ msgstr ""
|
|||
msgid "Update shelf"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:51
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56
|
||||
msgid "All books"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2743,30 +2756,30 @@ msgstr ""
|
|||
msgid "Create shelf"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:61
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:62
|
||||
msgid "Edit shelf"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:104
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:105
|
||||
msgid "Shelved"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:108
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:109
|
||||
msgid "Started"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:111
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:83
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:112
|
||||
msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:137
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:138
|
||||
msgid "This shelf is empty."
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:143
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:144
|
||||
msgid "Delete shelf"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2825,7 +2838,7 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:7
|
||||
#, python-format
|
||||
msgid "Users: <small>%(server_name)s</small>"
|
||||
msgid "Users: <small>%(instance_name)s</small>"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:22
|
||||
|
@ -2842,7 +2855,7 @@ msgid "Last Active"
|
|||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:38
|
||||
msgid "Remote server"
|
||||
msgid "Remote instance"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:47
|
||||
|
@ -2886,6 +2899,10 @@ msgstr ""
|
|||
msgid "Access level:"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3
|
||||
msgid "File exceeds maximum size: 10MB"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/views/import_data.py:67
|
||||
msgid "Not a valid csv file"
|
||||
msgstr ""
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 0.1.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-05-20 14:40-0700\n"
|
||||
"POT-Creation-Date: 2021-06-06 20:52+0000\n"
|
||||
"PO-Revision-Date: 2021-03-20 00:56+0000\n"
|
||||
"Last-Translator: Kana <gudzpoz@live.com>\n"
|
||||
"Language-Team: Mouse Reeve <LL@li.org>\n"
|
||||
|
@ -58,12 +58,12 @@ msgid "Book Title"
|
|||
msgstr "标题"
|
||||
|
||||
#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:84
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:115
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:85
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:116
|
||||
msgid "Rating"
|
||||
msgstr "评价"
|
||||
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:101
|
||||
#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:107
|
||||
msgid "Sort By"
|
||||
msgstr ""
|
||||
|
||||
|
@ -79,41 +79,41 @@ msgstr "升序排序"
|
|||
msgid "Descending"
|
||||
msgstr "升序排序"
|
||||
|
||||
#: bookwyrm/models/fields.py:24
|
||||
#: bookwyrm/models/fields.py:25
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid remote_id"
|
||||
msgstr "%(value)s 不是有效的 remote_id"
|
||||
|
||||
#: bookwyrm/models/fields.py:33 bookwyrm/models/fields.py:42
|
||||
#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43
|
||||
#, python-format
|
||||
msgid "%(value)s is not a valid username"
|
||||
msgstr "%(value)s 不是有效的用户名"
|
||||
|
||||
#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:155
|
||||
#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152
|
||||
msgid "username"
|
||||
msgstr "用户名"
|
||||
|
||||
#: bookwyrm/models/fields.py:170
|
||||
#: bookwyrm/models/fields.py:171
|
||||
msgid "A user with that username already exists."
|
||||
msgstr "已经存在使用该用户名的用户。"
|
||||
|
||||
#: bookwyrm/settings.py:155
|
||||
#: bookwyrm/settings.py:156
|
||||
msgid "English"
|
||||
msgstr "English(英语)"
|
||||
|
||||
#: bookwyrm/settings.py:156
|
||||
#: bookwyrm/settings.py:157
|
||||
msgid "German"
|
||||
msgstr "Deutsch(德语)"
|
||||
|
||||
#: bookwyrm/settings.py:157
|
||||
#: bookwyrm/settings.py:158
|
||||
msgid "Spanish"
|
||||
msgstr "Español(西班牙语)"
|
||||
|
||||
#: bookwyrm/settings.py:158
|
||||
#: bookwyrm/settings.py:159
|
||||
msgid "French"
|
||||
msgstr "Français(法语)"
|
||||
|
||||
#: bookwyrm/settings.py:159
|
||||
#: bookwyrm/settings.py:160
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "简体中文"
|
||||
|
||||
|
@ -260,7 +260,7 @@ msgstr "Goodreads key:"
|
|||
#: bookwyrm/templates/book/edit_book.html:263
|
||||
#: bookwyrm/templates/lists/form.html:42
|
||||
#: bookwyrm/templates/preferences/edit_user.html:70
|
||||
#: bookwyrm/templates/settings/announcement_form.html:65
|
||||
#: bookwyrm/templates/settings/announcement_form.html:69
|
||||
#: bookwyrm/templates/settings/edit_server.html:68
|
||||
#: bookwyrm/templates/settings/federated_server.html:98
|
||||
#: bookwyrm/templates/settings/site.html:97
|
||||
|
@ -386,7 +386,7 @@ msgstr "主题"
|
|||
msgid "Places"
|
||||
msgstr "地点"
|
||||
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:64
|
||||
#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12
|
||||
#: bookwyrm/templates/search/layout.html:25
|
||||
#: bookwyrm/templates/search/layout.html:50
|
||||
|
@ -400,7 +400,7 @@ msgstr "添加到列表"
|
|||
|
||||
#: bookwyrm/templates/book/book.html:297
|
||||
#: bookwyrm/templates/book/cover_modal.html:31
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Add"
|
||||
msgstr "添加"
|
||||
|
||||
|
@ -532,7 +532,7 @@ msgid "John Doe, Jane Smith"
|
|||
msgstr "张三, 李四"
|
||||
|
||||
#: bookwyrm/templates/book/edit_book.html:183
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:77
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
msgid "Cover"
|
||||
msgstr "封面"
|
||||
|
||||
|
@ -655,7 +655,7 @@ msgstr "跨站社区"
|
|||
|
||||
#: bookwyrm/templates/directory/directory.html:4
|
||||
#: bookwyrm/templates/directory/directory.html:9
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
#: bookwyrm/templates/layout.html:64
|
||||
msgid "Directory"
|
||||
msgstr "目录"
|
||||
|
||||
|
@ -854,7 +854,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:87
|
||||
#: bookwyrm/templates/layout.html:92
|
||||
msgid "Direct Messages"
|
||||
msgstr "私信"
|
||||
|
||||
|
@ -910,7 +910,6 @@ msgid "Updates"
|
|||
msgstr "更新"
|
||||
|
||||
#: bookwyrm/templates/feed/feed_layout.html:10
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
#: bookwyrm/templates/user/shelf/books_header.html:3
|
||||
msgid "Your books"
|
||||
msgstr "你的书目"
|
||||
|
@ -963,7 +962,7 @@ msgid "What are you reading?"
|
|||
msgstr "你在阅读什么?"
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:9
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
#: bookwyrm/templates/lists/list.html:135
|
||||
msgid "Search for a book"
|
||||
msgstr "搜索书目"
|
||||
|
||||
|
@ -983,7 +982,7 @@ msgstr "你可以在开始使用 %(site_name)s 后添加书目。"
|
|||
#: bookwyrm/templates/get_started/users.html:18
|
||||
#: bookwyrm/templates/get_started/users.html:19
|
||||
#: bookwyrm/templates/layout.html:37 bookwyrm/templates/layout.html:38
|
||||
#: bookwyrm/templates/lists/list.html:124
|
||||
#: bookwyrm/templates/lists/list.html:139
|
||||
#: bookwyrm/templates/search/layout.html:4
|
||||
#: bookwyrm/templates/search/layout.html:9
|
||||
msgid "Search"
|
||||
|
@ -999,7 +998,7 @@ msgid "Popular on %(site_name)s"
|
|||
msgstr "%(site_name)s 上的热门"
|
||||
|
||||
#: bookwyrm/templates/get_started/books.html:58
|
||||
#: bookwyrm/templates/lists/list.html:137
|
||||
#: bookwyrm/templates/lists/list.html:152
|
||||
msgid "No books found"
|
||||
msgstr "没有找到书目"
|
||||
|
||||
|
@ -1111,7 +1110,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:97
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:40
|
||||
msgid "Import Books"
|
||||
msgstr "导入书目"
|
||||
|
||||
|
@ -1196,14 +1195,14 @@ msgstr "书目"
|
|||
|
||||
#: bookwyrm/templates/import_status.html:114
|
||||
#: bookwyrm/templates/snippets/create_status_form.html:13
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:78
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:98
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:99
|
||||
msgid "Title"
|
||||
msgstr "标题"
|
||||
|
||||
#: bookwyrm/templates/import_status.html:117
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:79
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:101
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:102
|
||||
msgid "Author"
|
||||
msgstr "作者"
|
||||
|
||||
|
@ -1245,15 +1244,21 @@ msgstr "搜索书目或用户"
|
|||
msgid "Main navigation menu"
|
||||
msgstr "主导航菜单"
|
||||
|
||||
#: bookwyrm/templates/layout.html:61
|
||||
#: bookwyrm/templates/layout.html:58
|
||||
msgid "Feed"
|
||||
msgstr "动态"
|
||||
|
||||
#: bookwyrm/templates/layout.html:102
|
||||
#: bookwyrm/templates/layout.html:87
|
||||
#, fuzzy
|
||||
#| msgid "Your books"
|
||||
msgid "Your Books"
|
||||
msgstr "你的书目"
|
||||
|
||||
#: bookwyrm/templates/layout.html:97
|
||||
msgid "Settings"
|
||||
msgstr "设置"
|
||||
|
||||
#: bookwyrm/templates/layout.html:111
|
||||
#: bookwyrm/templates/layout.html:106
|
||||
#: bookwyrm/templates/settings/admin_layout.html:31
|
||||
#: bookwyrm/templates/settings/manage_invite_requests.html:15
|
||||
#: bookwyrm/templates/settings/manage_invites.html:3
|
||||
|
@ -1261,45 +1266,47 @@ msgstr "设置"
|
|||
msgid "Invites"
|
||||
msgstr "邀请"
|
||||
|
||||
#: bookwyrm/templates/layout.html:118
|
||||
#: bookwyrm/templates/layout.html:113
|
||||
msgid "Admin"
|
||||
msgstr "管理员"
|
||||
|
||||
#: bookwyrm/templates/layout.html:125
|
||||
#: bookwyrm/templates/layout.html:120
|
||||
msgid "Log out"
|
||||
msgstr "登出"
|
||||
|
||||
#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134
|
||||
#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129
|
||||
#: bookwyrm/templates/notifications.html:6
|
||||
#: bookwyrm/templates/notifications.html:11
|
||||
msgid "Notifications"
|
||||
msgstr "通知"
|
||||
|
||||
#: bookwyrm/templates/layout.html:154 bookwyrm/templates/layout.html:158
|
||||
#: 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:159
|
||||
#: bookwyrm/templates/layout.html:156
|
||||
msgid "password"
|
||||
msgstr "密码"
|
||||
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:36
|
||||
#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36
|
||||
msgid "Forgot your password?"
|
||||
msgstr "忘记了密码?"
|
||||
|
||||
#: bookwyrm/templates/layout.html:163 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10
|
||||
#: bookwyrm/templates/login.html:33
|
||||
msgid "Log in"
|
||||
msgstr "登录"
|
||||
|
||||
#: bookwyrm/templates/layout.html:171
|
||||
#: bookwyrm/templates/layout.html:168
|
||||
msgid "Join"
|
||||
msgstr "加入"
|
||||
|
||||
#: bookwyrm/templates/layout.html:206
|
||||
msgid "About this server"
|
||||
#, fuzzy
|
||||
#| msgid "About this server"
|
||||
msgid "About this instance"
|
||||
msgstr "关于本服务器"
|
||||
|
||||
#: bookwyrm/templates/layout.html:210
|
||||
|
@ -1361,7 +1368,7 @@ msgid "Discard"
|
|||
msgstr "削除"
|
||||
|
||||
#: bookwyrm/templates/lists/edit_form.html:5
|
||||
#: bookwyrm/templates/lists/list_layout.html:17
|
||||
#: bookwyrm/templates/lists/list_layout.html:16
|
||||
msgid "Edit List"
|
||||
msgstr "编辑列表"
|
||||
|
||||
|
@ -1410,62 +1417,63 @@ msgstr "任何人都可以向此列表中添加书目"
|
|||
msgid "This list is currently empty"
|
||||
msgstr "此列表当前是空的"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:65
|
||||
#: bookwyrm/templates/lists/list.html:66
|
||||
#, python-format
|
||||
msgid "Added by <a href=\"%(user_path)s\">%(username)s</a>"
|
||||
msgstr "由 <a href=\"%(user_path)s\">%(username)s</a> 添加"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:77
|
||||
#, fuzzy
|
||||
#| msgid "Sent"
|
||||
msgid "Set"
|
||||
msgstr "已发送"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:80
|
||||
#: bookwyrm/templates/lists/list.html:74
|
||||
#, fuzzy
|
||||
#| msgid "List curation:"
|
||||
msgid "List position"
|
||||
msgstr "列表策展:"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:86
|
||||
#: bookwyrm/templates/lists/list.html:81
|
||||
#, fuzzy
|
||||
#| msgid "Sent"
|
||||
msgid "Set"
|
||||
msgstr "已发送"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:89
|
||||
#: bookwyrm/templates/snippets/shelf_selector.html:26
|
||||
msgid "Remove"
|
||||
msgstr "移除"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:99 bookwyrm/templates/lists/list.html:111
|
||||
#: bookwyrm/templates/lists/list.html:103
|
||||
#: bookwyrm/templates/lists/list.html:120
|
||||
#, fuzzy
|
||||
#| msgid "Your Lists"
|
||||
msgid "Sort List"
|
||||
msgstr "你的列表"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:105
|
||||
#: bookwyrm/templates/lists/list.html:113
|
||||
#, fuzzy
|
||||
#| msgid "Directory"
|
||||
msgid "Direction"
|
||||
msgstr "目录"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:127
|
||||
msgid "Add Books"
|
||||
msgstr "添加书目"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:116
|
||||
#: bookwyrm/templates/lists/list.html:129
|
||||
msgid "Suggest Books"
|
||||
msgstr "推荐书目"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:125
|
||||
#: bookwyrm/templates/lists/list.html:140
|
||||
msgid "search"
|
||||
msgstr "搜索"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:131
|
||||
#: bookwyrm/templates/lists/list.html:146
|
||||
msgid "Clear search"
|
||||
msgstr "清除搜索"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:136
|
||||
#: bookwyrm/templates/lists/list.html:151
|
||||
#, python-format
|
||||
msgid "No books found matching the query \"%(query)s\""
|
||||
msgstr "没有符合 \"%(query)s\" 请求的书目"
|
||||
|
||||
#: bookwyrm/templates/lists/list.html:164
|
||||
#: bookwyrm/templates/lists/list.html:179
|
||||
msgid "Suggest"
|
||||
msgstr "推荐"
|
||||
|
||||
|
@ -1558,8 +1566,8 @@ msgstr "已解决"
|
|||
|
||||
#: bookwyrm/templates/moderation/reports.html:6
|
||||
#, python-format
|
||||
msgid "Reports: %(server_name)s"
|
||||
msgstr "报告: %(server_name)s"
|
||||
msgid "Reports: %(instance_name)s"
|
||||
msgstr "报告: %(instance_name)s"
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:8
|
||||
#: bookwyrm/templates/moderation/reports.html:17
|
||||
|
@ -1569,8 +1577,8 @@ msgstr "报告"
|
|||
|
||||
#: bookwyrm/templates/moderation/reports.html:14
|
||||
#, python-format
|
||||
msgid "Reports: <small>%(server_name)s</small>"
|
||||
msgstr "报告: <small>%(server_name)s</small>"
|
||||
msgid "Reports: <small>%(instance_name)s</small>"
|
||||
msgstr "报告: <small>%(instance_name)s</small>"
|
||||
|
||||
#: bookwyrm/templates/moderation/reports.html:28
|
||||
msgid "Resolved"
|
||||
|
@ -1771,6 +1779,26 @@ msgstr "个人资料"
|
|||
msgid "Relationships"
|
||||
msgstr "关系"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr "评价了"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr "写了书评给"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr "评论了"
|
||||
|
||||
#: bookwyrm/templates/rss/title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr "引用了"
|
||||
|
||||
#: bookwyrm/templates/search/book.html:64
|
||||
#, fuzzy
|
||||
#| msgid "Show results from other catalogues"
|
||||
|
@ -1828,7 +1856,9 @@ msgstr "管理用户"
|
|||
#: bookwyrm/templates/settings/admin_layout.html:39
|
||||
#: bookwyrm/templates/settings/federation.html:3
|
||||
#: bookwyrm/templates/settings/federation.html:5
|
||||
msgid "Federated Servers"
|
||||
#, fuzzy
|
||||
#| msgid "Federated Servers"
|
||||
msgid "Federated Instances"
|
||||
msgstr "互联的服务器"
|
||||
|
||||
#: bookwyrm/templates/settings/admin_layout.html:44
|
||||
|
@ -1882,6 +1912,7 @@ msgid "Back to list"
|
|||
msgstr "回到服务器列表"
|
||||
|
||||
#: bookwyrm/templates/settings/announcement.html:11
|
||||
#: bookwyrm/templates/settings/announcement_form.html:6
|
||||
#, fuzzy
|
||||
#| msgid "Announcements"
|
||||
msgid "Edit Announcement"
|
||||
|
@ -1923,7 +1954,7 @@ msgstr "出生日期:"
|
|||
msgid "Active:"
|
||||
msgstr "活跃"
|
||||
|
||||
#: bookwyrm/templates/settings/announcement_form.html:5
|
||||
#: bookwyrm/templates/settings/announcement_form.html:8
|
||||
#: bookwyrm/templates/settings/announcements.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Announcements"
|
||||
|
@ -1982,13 +2013,15 @@ msgstr "停用"
|
|||
#: bookwyrm/templates/settings/server_blocklist.html:3
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:20
|
||||
#, fuzzy
|
||||
#| msgid "Add cover"
|
||||
msgid "Add server"
|
||||
msgstr "添加封面"
|
||||
#| msgid "Instance Name:"
|
||||
msgid "Add instance"
|
||||
msgstr "实例名称"
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:7
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:7
|
||||
msgid "Back to server list"
|
||||
#, fuzzy
|
||||
#| msgid "Back to server list"
|
||||
msgid "Back to instance list"
|
||||
msgstr "回到服务器列表"
|
||||
|
||||
#: bookwyrm/templates/settings/edit_server.html:16
|
||||
|
@ -2103,8 +2136,10 @@ msgstr ""
|
|||
|
||||
#: bookwyrm/templates/settings/federation.html:19
|
||||
#: bookwyrm/templates/user_admin/server_filter.html:5
|
||||
msgid "Server name"
|
||||
msgstr "服务器名称"
|
||||
#, fuzzy
|
||||
#| msgid "Instance Name:"
|
||||
msgid "Instance name"
|
||||
msgstr "实例名称"
|
||||
|
||||
#: bookwyrm/templates/settings/federation.html:23
|
||||
msgid "Date federated"
|
||||
|
@ -2231,7 +2266,7 @@ msgid "Import Blocklist"
|
|||
msgstr "导入书目"
|
||||
|
||||
#: bookwyrm/templates/settings/server_blocklist.html:26
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:5
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
msgid "Success!"
|
||||
msgstr "成功!"
|
||||
|
||||
|
@ -2320,15 +2355,15 @@ msgstr "没有封面"
|
|||
msgid "<a href=\"%(path)s\">%(title)s</a> by "
|
||||
msgstr "<a href=\"%(path)s\">%(title)s</a> 来自"
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:9
|
||||
#: bookwyrm/templates/snippets/boost_button.html:10
|
||||
#: bookwyrm/templates/snippets/boost_button.html:20
|
||||
#: bookwyrm/templates/snippets/boost_button.html:21
|
||||
#, fuzzy
|
||||
#| msgid "boosted"
|
||||
msgid "Boost"
|
||||
msgstr "转发了"
|
||||
|
||||
#: bookwyrm/templates/snippets/boost_button.html:16
|
||||
#: bookwyrm/templates/snippets/boost_button.html:17
|
||||
#: bookwyrm/templates/snippets/boost_button.html:33
|
||||
#: bookwyrm/templates/snippets/boost_button.html:34
|
||||
#, fuzzy
|
||||
#| msgid "Un-boost status"
|
||||
msgid "Un-boost"
|
||||
|
@ -2422,13 +2457,13 @@ msgstr "删除这些阅读日期吗?"
|
|||
msgid "You are deleting this readthrough and its %(count)s associated progress updates."
|
||||
msgstr "你正要删除这篇阅读经过以及与之相关的 %(count)s 次进度更新。"
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:9
|
||||
#: bookwyrm/templates/snippets/fav_button.html:11
|
||||
#: bookwyrm/templates/snippets/fav_button.html:10
|
||||
#: bookwyrm/templates/snippets/fav_button.html:12
|
||||
msgid "Like"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/snippets/fav_button.html:17
|
||||
#: bookwyrm/templates/snippets/fav_button.html:18
|
||||
#: bookwyrm/templates/snippets/fav_button.html:19
|
||||
#, fuzzy
|
||||
#| msgid "Un-like status"
|
||||
msgid "Un-like"
|
||||
|
@ -2471,6 +2506,13 @@ msgstr "接受"
|
|||
msgid "No rating"
|
||||
msgstr "没有评价"
|
||||
|
||||
#: bookwyrm/templates/snippets/form_rate_stars.html:44
|
||||
#: bookwyrm/templates/snippets/stars.html:7
|
||||
#, python-format
|
||||
msgid "%(rating)s star"
|
||||
msgid_plural "%(rating)s stars"
|
||||
msgstr[0] ""
|
||||
|
||||
#: bookwyrm/templates/snippets/generated_status/goal.html:1
|
||||
#, python-format
|
||||
msgid "set a goal to read %(counter)s book in %(year)s"
|
||||
|
@ -2522,17 +2564,17 @@ msgstr "发布到消息流中"
|
|||
msgid "Set goal"
|
||||
msgstr "设置目标"
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:7
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:9
|
||||
#, python-format
|
||||
msgid "%(percent)s%% complete!"
|
||||
msgstr "完成了 %(percent)s%% !"
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:10
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#, python-format
|
||||
msgid "You've read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr "你已经阅读了 <a href=\"%(path)s\">%(goal_count)s 本书中的 %(read_count)s 本</a>。"
|
||||
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||
#: bookwyrm/templates/snippets/goal_progress.html:14
|
||||
#, python-format
|
||||
msgid "%(username)s has read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||
msgstr "%(username)s 已经阅读了 <a href=\"%(path)s\">%(goal_count)s 本书中的 %(read_count)s 本</a>。"
|
||||
|
@ -2641,26 +2683,6 @@ msgstr "注册"
|
|||
msgid "Report"
|
||||
msgstr "报告"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:5
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:35
|
||||
msgid "rated"
|
||||
msgstr "评价了"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:7
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:37
|
||||
msgid "reviewed"
|
||||
msgstr "写了书评给"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:9
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:39
|
||||
msgid "commented on"
|
||||
msgstr "评论了"
|
||||
|
||||
#: bookwyrm/templates/snippets/rss_title.html:11
|
||||
#: bookwyrm/templates/snippets/status/status_header.html:41
|
||||
msgid "quoted"
|
||||
msgstr "引用了"
|
||||
|
||||
#: bookwyrm/templates/snippets/search_result_text.html:36
|
||||
msgid "Import book"
|
||||
msgstr "导入书目"
|
||||
|
@ -2832,7 +2854,7 @@ msgstr "编辑书架"
|
|||
msgid "Update shelf"
|
||||
msgstr "更新书架"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:51
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56
|
||||
msgid "All books"
|
||||
msgstr "所有书目"
|
||||
|
||||
|
@ -2840,30 +2862,30 @@ msgstr "所有书目"
|
|||
msgid "Create shelf"
|
||||
msgstr "创建书架"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:61
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:62
|
||||
msgid "Edit shelf"
|
||||
msgstr "编辑书架"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:80
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:104
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:105
|
||||
msgid "Shelved"
|
||||
msgstr "上架时间"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:81
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:108
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:109
|
||||
msgid "Started"
|
||||
msgstr "开始时间"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:82
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:111
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:83
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:112
|
||||
msgid "Finished"
|
||||
msgstr "完成时间"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:137
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:138
|
||||
msgid "This shelf is empty."
|
||||
msgstr "此书架是空的。"
|
||||
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:143
|
||||
#: bookwyrm/templates/user/shelf/shelf.html:144
|
||||
msgid "Delete shelf"
|
||||
msgstr "删除书架"
|
||||
|
||||
|
@ -2924,8 +2946,8 @@ msgstr "回到报告"
|
|||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:7
|
||||
#, python-format
|
||||
msgid "Users: <small>%(server_name)s</small>"
|
||||
msgstr "用户: <small>%(server_name)s</small>"
|
||||
msgid "Users: <small>%(instance_name)s</small>"
|
||||
msgstr "用户: <small>%(instance_name)s</small>"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:22
|
||||
#: bookwyrm/templates/user_admin/username_filter.html:5
|
||||
|
@ -2941,7 +2963,7 @@ msgid "Last Active"
|
|||
msgstr "最后或缺"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:38
|
||||
msgid "Remote server"
|
||||
msgid "Remote instance"
|
||||
msgstr "移除服务器"
|
||||
|
||||
#: bookwyrm/templates/user_admin/user_admin.html:47
|
||||
|
@ -2989,6 +3011,10 @@ msgstr ""
|
|||
msgid "Access level:"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3
|
||||
msgid "File exceeds maximum size: 10MB"
|
||||
msgstr ""
|
||||
|
||||
#: bookwyrm/views/import_data.py:67
|
||||
#, fuzzy
|
||||
#| msgid "Email address:"
|
||||
|
@ -3004,6 +3030,23 @@ msgstr "没有找到使用该邮箱的用户。"
|
|||
msgid "A password reset link sent to %s"
|
||||
msgstr "密码重置连接已发送给 %s"
|
||||
|
||||
#~ msgid "Reports: <small>%(server_name)s</small>"
|
||||
#~ msgstr "报告: <small>%(server_name)s</small>"
|
||||
|
||||
#~ msgid "Federated Servers"
|
||||
#~ msgstr "互联的服务器"
|
||||
|
||||
#~ msgid "Server name"
|
||||
#~ msgstr "服务器名称"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Add cover"
|
||||
#~ msgid "Add server"
|
||||
#~ msgstr "添加封面"
|
||||
|
||||
#~ msgid "Remote server"
|
||||
#~ msgstr "移除服务器"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "BookWyrm users"
|
||||
#~ msgid "BookWyrm\\"
|
||||
|
@ -3054,12 +3097,12 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Enter a number."
|
||||
#~ msgstr "系列编号:"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "A user with this email already exists."
|
||||
#~ msgid "%(model_name)s with this %(field_labels)s already exists."
|
||||
#~ msgstr "已经存在使用该邮箱的用户。"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid remote_id"
|
||||
#~ msgid "Value %(value)r is not a valid choice."
|
||||
#~ msgstr "%(value)s 不是有效的 remote_id"
|
||||
|
@ -3069,7 +3112,7 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "This field cannot be null."
|
||||
#~ msgstr "此书架是空的。"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "A user with this email already exists."
|
||||
#~ msgid "%(model_name)s with this %(field_label)s already exists."
|
||||
#~ msgstr "已经存在使用该邮箱的用户。"
|
||||
|
@ -3119,7 +3162,7 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Positive small integer"
|
||||
#~ msgstr "无有效的邀请"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(value)s” is not a valid UUID."
|
||||
#~ msgstr "%(value)s 不是有效的用户名"
|
||||
|
@ -3134,12 +3177,12 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "One-to-one relationship"
|
||||
#~ msgstr "关系"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "Relationships"
|
||||
#~ msgid "%(from)s-%(to)s relationship"
|
||||
#~ msgstr "关系"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "Relationships"
|
||||
#~ msgid "%(from)s-%(to)s relationships"
|
||||
#~ msgstr "关系"
|
||||
|
@ -3199,7 +3242,7 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Order"
|
||||
#~ msgstr "排列顺序"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "%(value)s is not a valid username"
|
||||
#~ msgid "“%(pk)s” is not a valid value."
|
||||
#~ msgstr "%(value)s 不是有效的用户名"
|
||||
|
@ -3263,7 +3306,7 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "This is not a valid IPv6 address."
|
||||
#~ msgstr "邮箱地址:"
|
||||
|
||||
#, fuzzy, python-format
|
||||
#, fuzzy
|
||||
#~| msgid "No books found matching the query \"%(query)s\""
|
||||
#~ msgid "No %(verbose_name)s found matching the query"
|
||||
#~ msgstr "没有符合 \"%(query)s\" 请求的书目"
|
||||
|
@ -3282,11 +3325,9 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Matching Users"
|
||||
#~ msgstr "匹配的用户"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Set a reading goal for %(year)s"
|
||||
#~ msgstr "设定 %(year)s 的阅读目标"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "by %(author)s"
|
||||
#~ msgstr "由 %(author)s 所著"
|
||||
|
||||
|
@ -3299,15 +3340,12 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Date"
|
||||
#~ msgstr "日期"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">review</a>"
|
||||
#~ msgstr "回复了 <a href=\"%(user_path)s\">%(username)s</a> 的 <a href=\"%(status_path)s\">书评</a>"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">comment</a>"
|
||||
#~ msgstr "恢复了 <a href=\"%(user_path)s\">%(username)s</a> 的 <a href=\"%(status_path)s\">评论</a>"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "replied to <a href=\"%(user_path)s\">%(username)s's</a> <a href=\"%(status_path)s\">quote</a>"
|
||||
#~ msgstr "回复了 <a href=\"%(user_path)s\">%(username)s</a> 的 <a href=\"%(status_path)s\">引用</a>"
|
||||
|
||||
|
@ -3317,7 +3355,6 @@ msgstr "密码重置连接已发送给 %s"
|
|||
#~ msgid "Add tag"
|
||||
#~ msgstr "添加标签"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Books tagged \"%(tag.name)s\""
|
||||
#~ msgstr "标有 \"%(tag.name)s\" 标签的书"
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include /etc/nginx/conf.d/server_config;
|
||||
|
||||
upstream web {
|
||||
server web:8000;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include /etc/nginx/conf.d/server_config;
|
||||
|
||||
upstream web {
|
||||
server web:8000;
|
||||
}
|
||||
|
|
1
nginx/server_config
Normal file
1
nginx/server_config
Normal file
|
@ -0,0 +1 @@
|
|||
client_max_body_size 10m;
|
|
@ -1,6 +1,6 @@
|
|||
celery==4.4.2
|
||||
colorthief==0.2.1
|
||||
Django==3.2.0
|
||||
Django==3.2.4
|
||||
django-model-utils==4.0.0
|
||||
environs==7.2.0
|
||||
flower==0.9.4
|
||||
|
|
|
@ -2042,9 +2042,9 @@ to-regex-range@^5.0.1:
|
|||
is-number "^7.0.0"
|
||||
|
||||
trim-newlines@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30"
|
||||
integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
|
||||
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
|
||||
|
||||
trough@^1.0.0:
|
||||
version "1.0.5"
|
||||
|
|
Loading…
Reference in a new issue