From 73c30e8c9ad2af9dd2445d521d589d195a5b56d5 Mon Sep 17 00:00:00 2001 From: Ilona Brand Date: Sat, 13 Feb 2021 19:42:25 -0600 Subject: [PATCH 0001/1024] Add user default privacy setting to the privacy_select and user preferences --- bookwyrm/forms.py | 2 +- .../0046_user_default_post_privacy.py | 18 ++++++++++++++++++ bookwyrm/models/user.py | 6 +++++- bookwyrm/templates/preferences/edit_user.html | 6 ++++++ .../templates/snippets/privacy_select.html | 8 ++++---- 5 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 bookwyrm/migrations/0046_user_default_post_privacy.py diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index ba2fcc8ca..19f692db4 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -103,7 +103,7 @@ class EditUserForm(CustomForm): class Meta: model = models.User fields = [ - 'avatar', 'name', 'email', 'summary', 'manually_approves_followers' + 'avatar', 'name', 'email', 'summary', 'manually_approves_followers', 'default_post_privacy' ] help_texts = {f: None for f in fields} diff --git a/bookwyrm/migrations/0046_user_default_post_privacy.py b/bookwyrm/migrations/0046_user_default_post_privacy.py new file mode 100644 index 000000000..3f2254726 --- /dev/null +++ b/bookwyrm/migrations/0046_user_default_post_privacy.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.7 on 2021-02-14 00:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0045_auto_20210210_2114'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='default_post_privacy', + field=models.CharField(choices=[('public', 'Public'), ('unlisted', 'Unlisted'), ('followers', 'Followers'), ('direct', 'Direct')], default='public', max_length=255), + ), + ] diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index da717d2e1..fe21b58fa 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -22,7 +22,6 @@ from .base_model import BookWyrmModel from .federated_server import FederatedServer from . import fields, Review - class User(OrderedCollectionPageMixin, AbstractUser): ''' a user who wants to read books ''' username = fields.UsernameField() @@ -91,6 +90,11 @@ class User(OrderedCollectionPageMixin, AbstractUser): through_fields=('user', 'status'), related_name='favorite_statuses' ) + default_post_privacy = models.CharField( + max_length=255, + default='public', + choices=fields.PrivacyLevels.choices + ) remote_id = fields.RemoteIdField( null=True, unique=True, activitypub_field='id') created_date = models.DateTimeField(auto_now_add=True) diff --git a/bookwyrm/templates/preferences/edit_user.html b/bookwyrm/templates/preferences/edit_user.html index 798d2fcba..fc490b967 100644 --- a/bookwyrm/templates/preferences/edit_user.html +++ b/bookwyrm/templates/preferences/edit_user.html @@ -43,6 +43,12 @@ Edit Profile {{ form.manually_approves_followers }} +
+ +
{% endblock %} diff --git a/bookwyrm/templates/snippets/privacy_select.html b/bookwyrm/templates/snippets/privacy_select.html index a771c3d6d..aabdc8df8 100644 --- a/bookwyrm/templates/snippets/privacy_select.html +++ b/bookwyrm/templates/snippets/privacy_select.html @@ -5,16 +5,16 @@ {% endif %} From 18ba33e05032f51183d2818a91007a298001ec28 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 5 Apr 2021 13:49:21 -0700 Subject: [PATCH 0002/1024] Uses redis for storing suggested users --- bookwyrm/suggested_users.py | 106 ++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 bookwyrm/suggested_users.py diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py new file mode 100644 index 000000000..38dc37b0e --- /dev/null +++ b/bookwyrm/suggested_users.py @@ -0,0 +1,106 @@ +""" store recommended follows in redis """ +import math.floor +from django.dispatch import receiver +from django.db.models import signals, Q + +from bookwyrm import models +from bookwyrm.redis_store import RedisStore, r +from bookwyrm.views.helpers import get_annotated_users + + +class SuggestedUsers(RedisStore): + """ suggested users for a user """ + + max_length = 30 + + def get_rank(self, obj): + """ get computed rank """ + return obj.mutuals + (1.0 - (1.0 / (obj.shared_books + 1))) + + def store_id(self, user): # pylint: disable=no-self-use + """ the key used to store this user's recs """ + return "{:d}-suggestions".format(user.id) + + def get_counts_from_rank(self, rank): # pylint: disable=no-self-use + """ calculate mutuals count and shared books count from rank """ + return { + "mutuals": math.floor(rank), + "shared_books": int(1 / (-1 * (1 % rank - 1))), + } + + def get_objects_for_store(self, store): + """ a list of potential follows for a user """ + user = models.User.objects.get(id=store.split("-")[0]) + + return get_annotated_users( + user, + ~Q(id=user.id), + ~Q(followers=user), + ~Q(follower_requests=user), + bookwyrm_user=True, + ) + + def get_stores_for_object(self, obj): + """ given a user, who might want to follow them """ + return models.User.objects.filter( + local=True, + ).exclude(user_following=obj) + + def rerank_obj(self, obj): + """ update all the instances of this user with new ranks """ + stores = self.get_stores_for_object(obj) + pipeline = r.pipeline() + for store in stores: + pipeline.zadd(store, self.get_value(obj), xx=True) + pipeline.execute() + + def rerank_user_suggestions(self, user): + """ update the ranks of the follows suggested to a user """ + self.populate_store(self.store_id(user)) + + +suggested_users = SuggestedUsers() + + +@receiver(signals.post_save, sender=models.UserFollows) +# pylint: disable=unused-argument +def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): + """ remove a follow from the recs and update the ranks""" + if ( + not created + or not instance.user_subject.local + or not instance.user_object.discoverable + ): + return + suggested_users.bulk_remove_objects_from_store( + [instance.user_object], instance.user_subject + ) + suggested_users.rerank_obj(instance.user_object) + + +@receiver(signals.post_save, sender=models.ShelfBook) +@receiver(signals.post_delete, sender=models.ShelfBook) +# pylint: disable=unused-argument +def update_rank_on_shelving(sender, instance, *args, **kwargs): + """ when a user shelves or unshelves a book, re-compute their rank """ + if not instance.user.discoverable: + return + suggested_users.rerank_obj(instance.user) + + +@receiver(signals.post_save, sender=models.User) +# pylint: disable=unused-argument, too-many-arguments +def add_or_remove_on_discoverability_change( + sender, instance, created, raw, using, update_fields, **kwargs +): + """ make a user (un)discoverable """ + if not "discoverable" in update_fields: + return + + if created: + suggested_users.rerank_user_suggestions(instance) + + if instance.discoverable: + suggested_users.add_object_to_related_stores(instance) + elif not created and not instance.discoverable: + suggested_users.remove_object_from_related_stores(instance) From 03e5da12ddea4debf364b8ee734af7e8284a49e8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 6 Apr 2021 08:31:18 -0700 Subject: [PATCH 0003/1024] Call suggestions redis in feed --- bookwyrm/redis_store.py | 4 ++-- bookwyrm/suggested_users.py | 15 ++++++++++++++- bookwyrm/views/feed.py | 7 ++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index 4236d6df2..5a9bb2f69 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -56,9 +56,9 @@ class RedisStore(ABC): pipeline.zrem(store, -1, obj.id) pipeline.execute() - def get_store(self, store): # pylint: disable=no-self-use + def get_store(self, store, **kwargs): # pylint: disable=no-self-use """ load the values in a store """ - return r.zrevrange(store, 0, -1) + return r.zrevrange(store, 0, -1, **kwargs) def populate_store(self, store): """ go from zero to a store """ diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 38dc37b0e..c6e6af85a 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -11,7 +11,7 @@ from bookwyrm.views.helpers import get_annotated_users class SuggestedUsers(RedisStore): """ suggested users for a user """ - max_length = 30 + max_length = 10 def get_rank(self, obj): """ get computed rank """ @@ -58,6 +58,19 @@ class SuggestedUsers(RedisStore): """ update the ranks of the follows suggested to a user """ self.populate_store(self.store_id(user)) + def get_suggestions(self, user): + """ get suggestions """ + values = self.get_store(self.store_id(user), withscores=True) + results = [] + # annotate users with mutuals and shared book counts + for user_id, rank in values[:5]: + counts = self.get_counts_from_rank(rank) + user = models.User.objects.get(id=user_id) + user.mutuals = counts["mutuals"] + user.shared_books = counts["shared_books"] + results.append(user) + return results + suggested_users = SuggestedUsers() diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index cda115867..71e486f2b 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -11,7 +11,8 @@ from django.views import View from bookwyrm import activitystreams, forms, models from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH, STREAMS -from .helpers import get_user_from_username, privacy_filter, get_suggested_users +from bookwyrm.suggested_users import suggested_users +from .helpers import get_user_from_username, privacy_filter from .helpers import is_api_request, is_bookwyrm_request, object_visible_to_user @@ -33,14 +34,14 @@ class Feed(View): activities = activitystreams.streams[tab].get_activity_stream(request.user) paginated = Paginator(activities, PAGE_LENGTH) - suggested_users = get_suggested_users(request.user) + suggestions = suggested_users.get_suggestions(request.user) data = { **feed_page_data(request.user), **{ "user": request.user, "activities": paginated.page(page), - "suggested_users": suggested_users, + "suggested_users": suggestions, "tab": tab, "goal_form": forms.GoalForm(), "path": "/%s" % tab, From dda21195de2ae563da65e1f4471d01baec7d9879 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 23 Apr 2021 16:34:04 -0700 Subject: [PATCH 0004/1024] Correct calls to annotated user set --- bookwyrm/suggested_users.py | 25 ++++++++++++++++++------- bookwyrm/views/directory.py | 2 +- bookwyrm/views/helpers.py | 14 +++++++------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index c6e6af85a..eb1e8ebcb 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -1,5 +1,5 @@ """ store recommended follows in redis """ -import math.floor +import math from django.dispatch import receiver from django.db.models import signals, Q @@ -41,17 +41,28 @@ class SuggestedUsers(RedisStore): ) def get_stores_for_object(self, obj): + return [self.store_id(u) for u in self.get_users_for_object(obj)] + + def get_users_for_object(self, obj): # pylint: disable=no-self-use """ given a user, who might want to follow them """ return models.User.objects.filter( local=True, - ).exclude(user_following=obj) + ).exclude(following=obj) def rerank_obj(self, obj): """ update all the instances of this user with new ranks """ - stores = self.get_stores_for_object(obj) pipeline = r.pipeline() - for store in stores: - pipeline.zadd(store, self.get_value(obj), xx=True) + for store_user in self.get_users_for_object(obj): + annotated_user = get_annotated_users( + store_user, + id=obj.id, + ).first() + + pipeline.zadd( + self.store_id(store_user), + self.get_value(annotated_user), + xx=True + ) pipeline.execute() def rerank_user_suggestions(self, user): @@ -107,13 +118,13 @@ def add_or_remove_on_discoverability_change( sender, instance, created, raw, using, update_fields, **kwargs ): """ make a user (un)discoverable """ - if not "discoverable" in update_fields: + if not update_fields or not "discoverable" in update_fields: return if created: suggested_users.rerank_user_suggestions(instance) if instance.discoverable: - suggested_users.add_object_to_related_stores(instance) + suggested_users.rerank_obj(instance) elif not created and not instance.discoverable: suggested_users.remove_object_from_related_stores(instance) diff --git a/bookwyrm/views/directory.py b/bookwyrm/views/directory.py index 9504734e8..ae9dbe74f 100644 --- a/bookwyrm/views/directory.py +++ b/bookwyrm/views/directory.py @@ -46,5 +46,5 @@ class Directory(View): def post(self, request): """ join the directory """ request.user.discoverable = True - request.user.save() + request.user.save(update_fields=["discoverable"]) return redirect("directory") diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 75c5da8fe..f133d4ab6 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -207,27 +207,27 @@ def get_suggested_users(user): ) -def get_annotated_users(user, *args, **kwargs): +def get_annotated_users(viewer, *args, **kwargs): """ Users, annotated with things they have in common """ return ( models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs) - .exclude(Q(id__in=user.blocks.all()) | Q(blocks=user)) + .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) .annotate( mutuals=Count( "following", filter=Q( - ~Q(id=user.id), - ~Q(id__in=user.following.all()), - following__in=user.following.all(), + ~Q(id=viewer.id), + ~Q(id__in=viewer.following.all()), + following__in=viewer.following.all(), ), distinct=True, ), shared_books=Count( "shelfbook", filter=Q( - ~Q(id=user.id), + ~Q(id=viewer.id), shelfbook__book__parent_work__in=[ - s.book.parent_work for s in user.shelfbook_set.all() + s.book.parent_work for s in viewer.shelfbook_set.all() ], ), distinct=True, From 9880bdc75bdfbc50e9e5c0acf0ed4c989d89934a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 23 Apr 2021 18:26:48 -0700 Subject: [PATCH 0005/1024] Move anntotated users quuery into suggested users module --- bookwyrm/suggested_users.py | 36 ++++++++++++++++++++++++---- bookwyrm/views/directory.py | 4 ++-- bookwyrm/views/get_started.py | 3 +-- bookwyrm/views/helpers.py | 44 ----------------------------------- 4 files changed, 35 insertions(+), 52 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index eb1e8ebcb..2f2b750a2 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -1,17 +1,16 @@ """ store recommended follows in redis """ import math from django.dispatch import receiver -from django.db.models import signals, Q +from django.db.models import signals, Count, Q from bookwyrm import models from bookwyrm.redis_store import RedisStore, r -from bookwyrm.views.helpers import get_annotated_users class SuggestedUsers(RedisStore): """ suggested users for a user """ - max_length = 10 + max_length = 30 def get_rank(self, obj): """ get computed rank """ @@ -25,7 +24,7 @@ class SuggestedUsers(RedisStore): """ calculate mutuals count and shared books count from rank """ return { "mutuals": math.floor(rank), - "shared_books": int(1 / (-1 * (1 % rank - 1))), + "shared_books": int(1 / (-1 * (1 % rank - 1))) if rank else 0, } def get_objects_for_store(self, store): @@ -83,6 +82,35 @@ class SuggestedUsers(RedisStore): return results +def get_annotated_users(viewer, *args, **kwargs): + """ Users, annotated with things they have in common """ + return ( + models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs) + .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) + .annotate( + mutuals=Count( + "following", + filter=Q( + ~Q(id=viewer.id), + ~Q(id__in=viewer.following.all()), + following__in=viewer.following.all(), + ), + distinct=True, + ), + shared_books=Count( + "shelfbook", + filter=Q( + ~Q(id=viewer.id), + shelfbook__book__parent_work__in=[ + s.book.parent_work for s in viewer.shelfbook_set.all() + ], + ), + distinct=True, + ), + ) + ) + + suggested_users = SuggestedUsers() diff --git a/bookwyrm/views/directory.py b/bookwyrm/views/directory.py index ae9dbe74f..52e65c190 100644 --- a/bookwyrm/views/directory.py +++ b/bookwyrm/views/directory.py @@ -6,7 +6,7 @@ from django.template.response import TemplateResponse from django.views import View from django.utils.decorators import method_decorator -from .helpers import get_annotated_users +from bookwyrm import suggested_users # pylint: disable=no-self-use @method_decorator(login_required, name="dispatch") @@ -29,7 +29,7 @@ class Directory(View): if scope == "local": filters["local"] = True - users = get_annotated_users(request.user, **filters) + users = suggested_users.get_annotated_users(request.user, **filters) sort = request.GET.get("sort") if sort == "recent": users = users.order_by("-last_active_date") diff --git a/bookwyrm/views/get_started.py b/bookwyrm/views/get_started.py index a21723a38..92da0c19b 100644 --- a/bookwyrm/views/get_started.py +++ b/bookwyrm/views/get_started.py @@ -13,7 +13,6 @@ 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 @@ -120,7 +119,7 @@ class GetStartedUsers(View): ) if user_results.count() < 5: - suggested_users = get_suggested_users(request.user) + suggested_users = None#get_suggested_users(request.user) data = { "suggested_users": list(user_results) + list(suggested_users), diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index f133d4ab6..057027d4e 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -190,47 +190,3 @@ def get_discover_books(): .order_by("-review__published_date__max")[:6] ) ) - - -def get_suggested_users(user): - """ bookwyrm users you don't already know """ - return ( - get_annotated_users( - user, - ~Q(id=user.id), - ~Q(followers=user), - ~Q(follower_requests=user), - bookwyrm_user=True, - ) - .order_by("-mutuals", "-last_active_date") - .all()[:5] - ) - - -def get_annotated_users(viewer, *args, **kwargs): - """ Users, annotated with things they have in common """ - return ( - models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs) - .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) - .annotate( - mutuals=Count( - "following", - filter=Q( - ~Q(id=viewer.id), - ~Q(id__in=viewer.following.all()), - following__in=viewer.following.all(), - ), - distinct=True, - ), - shared_books=Count( - "shelfbook", - filter=Q( - ~Q(id=viewer.id), - shelfbook__book__parent_work__in=[ - s.book.parent_work for s in viewer.shelfbook_set.all() - ], - ), - distinct=True, - ), - ) - ) From 4fb85ced5f3a9ab1bd57de402bfb26216bed4fae Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 24 Apr 2021 11:16:35 -0700 Subject: [PATCH 0006/1024] Updates logic for new and newly discoverable users --- bookwyrm/suggested_users.py | 13 +++++++------ bookwyrm/views/user.py | 6 +++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 2f2b750a2..ec6e5caa8 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -48,7 +48,7 @@ class SuggestedUsers(RedisStore): local=True, ).exclude(following=obj) - def rerank_obj(self, obj): + def rerank_obj(self, obj, update_only=True): """ update all the instances of this user with new ranks """ pipeline = r.pipeline() for store_user in self.get_users_for_object(obj): @@ -60,7 +60,7 @@ class SuggestedUsers(RedisStore): pipeline.zadd( self.store_id(store_user), self.get_value(annotated_user), - xx=True + xx=update_only ) pipeline.execute() @@ -146,13 +146,14 @@ def add_or_remove_on_discoverability_change( sender, instance, created, raw, using, update_fields, **kwargs ): """ make a user (un)discoverable """ - if not update_fields or not "discoverable" in update_fields: - return - if created: suggested_users.rerank_user_suggestions(instance) + if not created and (not update_fields or not "discoverable" in update_fields): + return + if instance.discoverable: - suggested_users.rerank_obj(instance) + suggested_users.rerank_obj(instance, update_only=False) + elif not created and not instance.discoverable: suggested_users.remove_object_from_related_stores(instance) diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index aba804d8b..6cbb82ef5 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -181,7 +181,11 @@ def save_user_form(form): extension = form.files["avatar"].name.split(".")[-1] filename = "%s.%s" % (uuid4(), extension) user.avatar.save(filename, image, save=False) - user.save() + + updated_fields = None + if form.initial["discoverable"] != form.cleaned_data["discoverable"]: + updated_fields = ["discoverable"] + user.save(updated_fields=updated_fields) return user From 5d9cfe0276109ecfc20f233b41aaf909975b09ed Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 26 Apr 2021 10:34:40 -0700 Subject: [PATCH 0007/1024] Fixes followers/following logic on suggested users --- bookwyrm/suggested_users.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index ec6e5caa8..482935ff3 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -89,11 +89,11 @@ def get_annotated_users(viewer, *args, **kwargs): .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) .annotate( mutuals=Count( - "following", + "followers", filter=Q( ~Q(id=viewer.id), ~Q(id__in=viewer.following.all()), - following__in=viewer.following.all(), + followers__in=viewer.following.all(), ), distinct=True, ), From 32b3a02a17df9279fe0081da04254750f944d4a8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 26 Apr 2021 11:09:24 -0700 Subject: [PATCH 0008/1024] Fixes reverse rank calculation --- bookwyrm/suggested_users.py | 2 +- bookwyrm/tests/test_suggested_users.py | 69 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/tests/test_suggested_users.py diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 171e8d378..9bc51aa2d 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -24,7 +24,7 @@ class SuggestedUsers(RedisStore): """calculate mutuals count and shared books count from rank""" return { "mutuals": math.floor(rank), - "shared_books": int(1 / (-1 * (1 % rank - 1))) if rank else 0, + "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1, } def get_objects_for_store(self, store): diff --git a/bookwyrm/tests/test_suggested_users.py b/bookwyrm/tests/test_suggested_users.py new file mode 100644 index 000000000..0b37cd1a1 --- /dev/null +++ b/bookwyrm/tests/test_suggested_users.py @@ -0,0 +1,69 @@ +""" testing user follow suggestions """ +from collections import namedtuple +from unittest.mock import patch + +from django.test import TestCase + +from bookwyrm import models +from bookwyrm.suggested_users import suggested_users + + +@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") +@patch("bookwyrm.activitystreams.ActivityStream.add_status") +class SuggestedUsers(TestCase): + """using redis to build activity streams""" + + def setUp(self): + """use a test csv""" + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.book = models.Edition.objects.create(title="test book") + + def test_get_ramk(self, *_): + """a float that reflects both the mutuals count and shared books""" + Mock = namedtuple("AnnotatedUserMock", ("mutuals", "shared_books")) + annotated_user_mock = Mock(3, 27) + rank = suggested_users.get_rank(annotated_user_mock) + self.assertEqual(rank, 3.9642857142857144) + + def test_store_id(self, *_): + """redis key generation""" + self.assertEqual( + suggested_users.store_id(self.local_user), + "{:d}-suggestions".format(self.local_user.id), + ) + + def test_get_counts_from_rank(self, *_): + """reverse the rank computation to get the mutuals and shared books counts""" + counts = suggested_users.get_counts_from_rank(3.9642857142857144) + self.assertEqual(counts["mutuals"], 3) + self.assertEqual(counts["shared_books"], 27) + + def test_get_objects_for_store(self, *_): + """list of people to follow for a given user""" + + mutual_user = models.User.objects.create_user( + "rat", "rat@local.rat", "password", local=True, localname="rat" + ) + suggestable_user = models.User.objects.create_user( + "nutria", + "nutria@nutria.nutria", + "password", + local=True, + localname="nutria", + discoverable=True, + ) + + # you follow rat + mutual_user.followers.add(self.local_user) + # rat follows the suggested user + suggestable_user.followers.add(mutual_user) + + results = suggested_users.get_objects_for_store( + "{:d}-suggestions".format(self.local_user.id) + ) + self.assertEqual(results.count(), 1) + match = results.first() + self.assertEqual(match.id, suggestable_user.id) + self.assertEqual(match.mutuals, 1) From 6b3447761f2f27c1c2d09a545fff1edbb6421ec4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 20 May 2021 18:16:35 -0700 Subject: [PATCH 0009/1024] Adds book format field with choices --- ...l_format_edition_physical_format_detail.py | 35 +++++++++++++++++++ bookwyrm/models/book.py | 12 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/migrations/0076_rename_physical_format_edition_physical_format_detail.py diff --git a/bookwyrm/migrations/0076_rename_physical_format_edition_physical_format_detail.py b/bookwyrm/migrations/0076_rename_physical_format_edition_physical_format_detail.py new file mode 100644 index 000000000..05ad1a2ba --- /dev/null +++ b/bookwyrm/migrations/0076_rename_physical_format_edition_physical_format_detail.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2 on 2021-05-21 00:17 + +from django.db import migrations +import bookwyrm + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0075_announcement"), + ] + + operations = [ + migrations.RenameField( + model_name="edition", + old_name="physical_format", + new_name="physical_format_detail", + ), + migrations.AddField( + model_name="edition", + name="physical_format", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("AudiobookFormat", "Audiobookformat"), + ("EBook", "Ebook"), + ("GraphicNovel", "Graphicnovel"), + ("Hardcover", "Hardcover"), + ("Paperback", "Paperback"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index 869ff04d2..ae79223d3 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -169,6 +169,13 @@ class Work(OrderedCollectionPageMixin, Book): deserialize_reverse_fields = [("editions", "editions")] +# https://schema.org/BookFormatType +FormatChoices = models.TextChoices( + "FormatChoices", + "AudiobookFormat EBook GraphicNovel Hardcover Paperback", +) + + class Edition(Book): """an edition of a book""" @@ -186,7 +193,10 @@ class Edition(Book): max_length=255, blank=True, null=True, deduplication_field=True ) pages = fields.IntegerField(blank=True, null=True) - physical_format = fields.CharField(max_length=255, blank=True, null=True) + physical_format = fields.CharField( + max_length=255, choices=FormatChoices.choices, null=True, blank=True + ) + physical_format_detail = fields.CharField(max_length=255, blank=True, null=True) publishers = fields.ArrayField( models.CharField(max_length=255), blank=True, default=list ) From 2ff79c99530af999cada1d5166c5e25c329b223d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 09:55:38 -0700 Subject: [PATCH 0010/1024] Fixes python formatting --- bookwyrm/views/get_started.py | 4 ++-- bookwyrm/views/helpers.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bookwyrm/views/get_started.py b/bookwyrm/views/get_started.py index 1bed03df7..bae232120 100644 --- a/bookwyrm/views/get_started.py +++ b/bookwyrm/views/get_started.py @@ -120,9 +120,9 @@ class GetStartedUsers(View): if user_results.count() < 5: suggested_users = [] # TODO: get_suggested_users(request.user) - user_results = list(user_results) + list(suggested_users)) + user_results = list(user_results) + list(suggested_users) data = { "suggested_users": user_results, } - return TemplateResponse(request, "get_started/users.html", data) \ No newline at end of file + return TemplateResponse(request, "get_started/users.html", data) diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index b4dcc9045..169e59b41 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -172,4 +172,4 @@ def get_discover_books(): .annotate(Max("review__published_date")) .order_by("-review__published_date__max")[:6] ) - ) \ No newline at end of file + ) From f98576bc252a7cc97a671b8b19975d473b9d4d63 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 11:01:35 -0700 Subject: [PATCH 0011/1024] Only create suggestions stores for local users --- bookwyrm/suggested_users.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 9bc51aa2d..a6d09ecd2 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -146,14 +146,18 @@ def add_or_remove_on_discoverability_change( sender, instance, created, raw, using, update_fields, **kwargs ): """make a user (un)discoverable""" - if created: + if created and instance.local: + # a new user is found, create suggestions for them suggested_users.rerank_user_suggestions(instance) if not created and (not update_fields or not "discoverable" in update_fields): + # this is just a regular old user update, not related to discoverability return if instance.discoverable: + # add this user to all suitable stores suggested_users.rerank_obj(instance, update_only=False) elif not created and not instance.discoverable: + # remove this user from all suitable stores suggested_users.remove_object_from_related_stores(instance) From 0044dc65875a628c998af147664c5ea5bc6cd497 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 11:20:39 -0700 Subject: [PATCH 0012/1024] Show suggested users when the feed is empty --- bookwyrm/suggested_users.py | 2 ++ bookwyrm/templates/feed/feed.html | 16 ++++++---- bookwyrm/templates/feed/suggested_users.html | 29 ++++--------------- bookwyrm/templates/get_started/users.html | 2 +- .../templates/snippets/suggested_users.html | 25 ++++++++++++++++ 5 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 bookwyrm/templates/snippets/suggested_users.html diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index a6d09ecd2..7b20461a6 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -66,6 +66,8 @@ class SuggestedUsers(RedisStore): def rerank_user_suggestions(self, user): """update the ranks of the follows suggested to a user""" + if not user.local: + raise ValueError('Attempting to create suggestions for remote user: ', user.id) self.populate_store(self.store_id(user)) def get_suggestions(self, user): diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 21e71ae18..78b03436e 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -44,18 +44,22 @@ {# activity feed #} {% if not activities %} -

{% trans "There aren't any activities right now! Try following a user to get started" %}

+
+

{% trans "There aren't any activities right now! Try following a user to get started" %}

+ + {% if suggested_users %} + {# suggested users for when things are very lonely #} + {% include 'feed/suggested_users.html' with suggested_users=suggested_users %} +
+{% endif %} + {% endif %} {% for activity in activities %} {% if not activities.number > 1 and forloop.counter0 == 2 and suggested_users %} {# suggested users on the first page, two statuses down #} -
-

{% trans "Who to follow" %}

- {% include 'feed/suggested_users.html' with suggested_users=suggested_users %} - View directory -
+{% include 'feed/suggested_users.html' with suggested_users=suggested_users %} {% endif %}
{% include 'snippets/status/status.html' with status=activity %} diff --git a/bookwyrm/templates/feed/suggested_users.html b/bookwyrm/templates/feed/suggested_users.html index eb146f7eb..c095faa55 100644 --- a/bookwyrm/templates/feed/suggested_users.html +++ b/bookwyrm/templates/feed/suggested_users.html @@ -1,25 +1,6 @@ {% load i18n %} -{% load utilities %} -{% load humanize %} -
- {% for user in suggested_users %} -
-
- - {% include 'snippets/avatar.html' with user=user large=True %} - {{ user.display_name|truncatechars:10 }} - @{{ user|username|truncatechars:8 }} - - {% include 'snippets/follow_button.html' with user=user minimal=True %} - {% if user.mutuals %} -

- {% blocktrans with mutuals=user.mutuals|intcomma count counter=user.mutuals %}{{ mutuals }} follower you follow{% plural %}{{ mutuals }} followers you follow{% endblocktrans %} -

- {% elif user.shared_books %} -

{% blocktrans with shared_books=user.shared_books|intcomma count counter=user.shared_books %}{{ shared_books }} book on your shelves{% plural %}{{ shared_books }} books on your shelves{% endblocktrans %}

- {% endif %} -
-
- {% endfor %} -
- +
+

{% trans "Who to follow" %}

+ {% include 'snippets/suggested_users.html' with suggested_users=suggested_users %} + View directory +
diff --git a/bookwyrm/templates/get_started/users.html b/bookwyrm/templates/get_started/users.html index 259f06d34..753691fbd 100644 --- a/bookwyrm/templates/get_started/users.html +++ b/bookwyrm/templates/get_started/users.html @@ -22,7 +22,7 @@
- {% include 'feed/suggested_users.html' with suggested_users=suggested_users %} + {% include 'snippets/suggested_users.html' with suggested_users=suggested_users %} {% endblock %} diff --git a/bookwyrm/templates/snippets/suggested_users.html b/bookwyrm/templates/snippets/suggested_users.html new file mode 100644 index 000000000..eb146f7eb --- /dev/null +++ b/bookwyrm/templates/snippets/suggested_users.html @@ -0,0 +1,25 @@ +{% load i18n %} +{% load utilities %} +{% load humanize %} +
+ {% for user in suggested_users %} +
+
+ + {% include 'snippets/avatar.html' with user=user large=True %} + {{ user.display_name|truncatechars:10 }} + @{{ user|username|truncatechars:8 }} + + {% include 'snippets/follow_button.html' with user=user minimal=True %} + {% if user.mutuals %} +

+ {% blocktrans with mutuals=user.mutuals|intcomma count counter=user.mutuals %}{{ mutuals }} follower you follow{% plural %}{{ mutuals }} followers you follow{% endblocktrans %} +

+ {% elif user.shared_books %} +

{% blocktrans with shared_books=user.shared_books|intcomma count counter=user.shared_books %}{{ shared_books }} book on your shelves{% plural %}{{ shared_books }} books on your shelves{% endblocktrans %}

+ {% endif %} +
+
+ {% endfor %} +
+ From 29130d5f44b1f5d87e9003536421da2de03ceac8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 11:53:20 -0700 Subject: [PATCH 0013/1024] Detect new users and users with updated discoverability --- bookwyrm/suggested_users.py | 38 ++++++++++++++++++++++++++----------- bookwyrm/views/directory.py | 2 +- bookwyrm/views/user.py | 5 +---- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 7b20461a6..906131917 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -67,7 +67,7 @@ class SuggestedUsers(RedisStore): def rerank_user_suggestions(self, user): """update the ranks of the follows suggested to a user""" if not user.local: - raise ValueError('Attempting to create suggestions for remote user: ', user.id) + raise ValueError("Trying to create suggestions for remote user: ", user.id) self.populate_store(self.store_id(user)) def get_suggestions(self, user): @@ -144,22 +144,38 @@ def update_rank_on_shelving(sender, instance, *args, **kwargs): @receiver(signals.post_save, sender=models.User) # pylint: disable=unused-argument, too-many-arguments -def add_or_remove_on_discoverability_change( - sender, instance, created, raw, using, update_fields, **kwargs -): - """make a user (un)discoverable""" - if created and instance.local: - # a new user is found, create suggestions for them - suggested_users.rerank_user_suggestions(instance) +def add_new_user(sender, instance, created, **kwargs): + """a new user, wow how cool""" + if not created or not instance.local: + return + # a new user is found, create suggestions for them + suggested_users.rerank_user_suggestions(instance) - if not created and (not update_fields or not "discoverable" in update_fields): - # this is just a regular old user update, not related to discoverability + if instance.discoverable: + # idk why this would happen, but the new user is already discoverable + # so we should add them to the suggestions + suggested_users.rerank_obj(instance, update_only=False) + + +@receiver(signals.pre_save, sender=models.User) +# pylint: disable=unused-argument, too-many-arguments +def set_discoverability(sender, instance, **kwargs): + """make a user (un)discoverable""" + if not instance.id: + # this means the user was created, which is handled in `add_new_user` return + was_discoverable = models.User.objects.get(id=instance.id).discoverable + if was_discoverable == instance.discoverable: + # no change in discoverability, who cares + return + + # the user is newly available if instance.discoverable: # add this user to all suitable stores suggested_users.rerank_obj(instance, update_only=False) - elif not created and not instance.discoverable: + # the user is newly un-available + else: # remove this user from all suitable stores suggested_users.remove_object_from_related_stores(instance) diff --git a/bookwyrm/views/directory.py b/bookwyrm/views/directory.py index 108537cc7..0dc3f8f5a 100644 --- a/bookwyrm/views/directory.py +++ b/bookwyrm/views/directory.py @@ -40,5 +40,5 @@ class Directory(View): def post(self, request): """join the directory""" request.user.discoverable = True - request.user.save(update_fields=["discoverable"]) + request.user.save() return redirect("directory") diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index 2ab38a43d..9684a68fe 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -157,10 +157,7 @@ def save_user_form(form): filename = "%s.%s" % (uuid4(), extension) user.avatar.save(filename, image, save=False) - updated_fields = None - if form.initial["discoverable"] != form.cleaned_data["discoverable"]: - updated_fields = ["discoverable"] - user.save(updated_fields=updated_fields) + user.save() return user From f849d785a5955f977ad7eb8892d6a8590c9620e2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 12:10:14 -0700 Subject: [PATCH 0014/1024] Functional un-discoverable setting --- bookwyrm/suggested_users.py | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 906131917..ae60a769b 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -146,36 +146,12 @@ def update_rank_on_shelving(sender, instance, *args, **kwargs): # pylint: disable=unused-argument, too-many-arguments def add_new_user(sender, instance, created, **kwargs): """a new user, wow how cool""" - if not created or not instance.local: - return - # a new user is found, create suggestions for them - suggested_users.rerank_user_suggestions(instance) + if created and instance.local: + # a new user is found, create suggestions for them + suggested_users.rerank_user_suggestions(instance) + # TODO: this happens on every save, not just when discoverability changes if instance.discoverable: - # idk why this would happen, but the new user is already discoverable - # so we should add them to the suggestions suggested_users.rerank_obj(instance, update_only=False) - - -@receiver(signals.pre_save, sender=models.User) -# pylint: disable=unused-argument, too-many-arguments -def set_discoverability(sender, instance, **kwargs): - """make a user (un)discoverable""" - if not instance.id: - # this means the user was created, which is handled in `add_new_user` - return - - was_discoverable = models.User.objects.get(id=instance.id).discoverable - if was_discoverable == instance.discoverable: - # no change in discoverability, who cares - return - - # the user is newly available - if instance.discoverable: - # add this user to all suitable stores - suggested_users.rerank_obj(instance, update_only=False) - - # the user is newly un-available - else: - # remove this user from all suitable stores + elif not created: suggested_users.remove_object_from_related_stores(instance) From 42699a8d252f08883a5c7ebc46dd9ea5dc27c46b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 12:20:23 -0700 Subject: [PATCH 0015/1024] Update your own suggestions on shelve --- bookwyrm/suggested_users.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index ae60a769b..3136803db 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -137,6 +137,11 @@ def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): # pylint: disable=unused-argument def update_rank_on_shelving(sender, instance, *args, **kwargs): """when a user shelves or unshelves a book, re-compute their rank""" + # if it's a local user, re-calculate who is rec'ed to them + if instance.user.local: + suggested_users.rerank_user_suggestions(instance.user) + + # if the user is discoverable, update their rankings if not instance.user.discoverable: return suggested_users.rerank_obj(instance.user) From 9250b8b85dc1a0c7bb9d300c0cf781e9f8c03df1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 12:56:37 -0700 Subject: [PATCH 0016/1024] Handle follow/unfollow --- bookwyrm/suggested_users.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 3136803db..d0937cfd8 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -70,6 +70,10 @@ class SuggestedUsers(RedisStore): raise ValueError("Trying to create suggestions for remote user: ", user.id) self.populate_store(self.store_id(user)) + def remove_suggestion(self, user, suggested_user): + """take a user out of someone's suggestions""" + self.bulk_remove_objects_from_store([suggested_user], self.store_id(user)) + def get_suggestions(self, user): """get suggestions""" values = self.get_store(self.store_id(user), withscores=True) @@ -120,18 +124,22 @@ suggested_users = SuggestedUsers() # pylint: disable=unused-argument def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): """remove a follow from the recs and update the ranks""" - if ( - not created - or not instance.user_subject.local - or not instance.user_object.discoverable - ): + if not created or not instance.user_object.discoverable: return - suggested_users.bulk_remove_objects_from_store( - [instance.user_object], instance.user_subject - ) + + if instance.user_subject.local: + suggested_users.remove_suggestion(instance.user_subject, instance.user_object) suggested_users.rerank_obj(instance.user_object) +@receiver(signals.post_delete, sender=models.UserFollows) +# pylint: disable=unused-argument +def update_suggestions_on_unfollow(sender, instance, **kwargs): + """update rankings, but don't re-suggest because it was probably intentional""" + if instance.user_object.discoverable: + suggested_users.rerank_obj(instance.user_object) + + @receiver(signals.post_save, sender=models.ShelfBook) @receiver(signals.post_delete, sender=models.ShelfBook) # pylint: disable=unused-argument From 644e5926db4cbb116285a18832a62ccb95a8aa70 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 14:05:59 -0700 Subject: [PATCH 0017/1024] Remove suggested users on block --- bookwyrm/suggested_users.py | 12 +++++++++++- bookwyrm/templates/get_started/users.html | 2 +- bookwyrm/views/get_started.py | 11 ++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index d0937cfd8..a98da13e7 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -132,6 +132,16 @@ def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): suggested_users.rerank_obj(instance.user_object) +@receiver(signals.post_save, sender=models.UserBlocks) +# pylint: disable=unused-argument +def update_suggestions_on_block(sender, instance, *args, **kwargs): + """remove blocked users from recs""" + if instance.user_subject.local: + suggested_users.remove_suggestion(instance.user_subject, instance.user_object) + if instance.user_object.local: + suggested_users.remove_suggestion(instance.user_object, instance.user_subject) + + @receiver(signals.post_delete, sender=models.UserFollows) # pylint: disable=unused-argument def update_suggestions_on_unfollow(sender, instance, **kwargs): @@ -163,7 +173,7 @@ def add_new_user(sender, instance, created, **kwargs): # a new user is found, create suggestions for them suggested_users.rerank_user_suggestions(instance) - # TODO: this happens on every save, not just when discoverability changes + # this happens on every save, not just when discoverability changes, annoyingly if instance.discoverable: suggested_users.rerank_obj(instance, update_only=False) elif not created: diff --git a/bookwyrm/templates/get_started/users.html b/bookwyrm/templates/get_started/users.html index 753691fbd..7ec7ed9d3 100644 --- a/bookwyrm/templates/get_started/users.html +++ b/bookwyrm/templates/get_started/users.html @@ -9,7 +9,7 @@
- {% if request.GET.query and not user_results %} + {% if request.GET.query and no_results %}

{% blocktrans with query=request.GET.query %}No users found for "{{ query }}"{% endblocktrans %}

{% endif %}
diff --git a/bookwyrm/views/get_started.py b/bookwyrm/views/get_started.py index bae232120..eeef1d9e2 100644 --- a/bookwyrm/views/get_started.py +++ b/bookwyrm/views/get_started.py @@ -13,6 +13,7 @@ from django.views import View from bookwyrm import forms, models from bookwyrm.connectors import connector_manager +from bookwyrm.suggested_users import suggested_users from .user import save_user_form @@ -117,12 +118,12 @@ class GetStartedUsers(View): ) .order_by("-similarity")[:5] ) + data = {"no_results": not user_results} if user_results.count() < 5: - suggested_users = [] # TODO: get_suggested_users(request.user) - user_results = list(user_results) + list(suggested_users) + user_results = list(user_results) + suggested_users.get_suggestions( + request.user + ) - data = { - "suggested_users": user_results, - } + data["suggested_users"] = user_results return TemplateResponse(request, "get_started/users.html", data) From edfc27a3cdccdee39d8f2881fd6143075bc9cd6c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 15:53:07 -0700 Subject: [PATCH 0018/1024] Moves suggestion logic to celery --- bookwyrm/redis_store.py | 2 +- bookwyrm/suggested_users.py | 63 +++++++++++++++++++++++++++---------- celerywyrm/celery.py | 1 + 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index b38c0e67b..fa5c73a53 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -50,7 +50,7 @@ class RedisStore(ABC): pipeline.execute() def bulk_remove_objects_from_store(self, objs, store): - """remoev a list of objects from a given store""" + """remove a list of objects from a given store""" pipeline = r.pipeline() for obj in objs[: self.max_length]: pipeline.zrem(store, -1, obj.id) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index a98da13e7..bce3e5f13 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -5,6 +5,7 @@ from django.db.models import signals, Count, Q from bookwyrm import models from bookwyrm.redis_store import RedisStore, r +from bookwyrm.tasks import app class SuggestedUsers(RedisStore): @@ -18,6 +19,8 @@ class SuggestedUsers(RedisStore): def store_id(self, user): # pylint: disable=no-self-use """the key used to store this user's recs""" + if isinstance(user, int): + return "{:d}-suggestions".format(user) return "{:d}-suggestions".format(user.id) def get_counts_from_rank(self, rank): # pylint: disable=no-self-use @@ -46,7 +49,9 @@ class SuggestedUsers(RedisStore): """given a user, who might want to follow them""" return models.User.objects.filter( local=True, - ).exclude(following=obj) + ).exclude( + Q(id=obj.id) | Q(followers=obj) | Q(id__in=obj.blocks.all()) | Q(blocks=obj) + ) def rerank_obj(self, obj, update_only=True): """update all the instances of this user with new ranks""" @@ -56,6 +61,8 @@ class SuggestedUsers(RedisStore): store_user, id=obj.id, ).first() + if not annotated_user: + continue pipeline.zadd( self.store_id(store_user), @@ -66,8 +73,6 @@ class SuggestedUsers(RedisStore): def rerank_user_suggestions(self, user): """update the ranks of the follows suggested to a user""" - if not user.local: - raise ValueError("Trying to create suggestions for remote user: ", user.id) self.populate_store(self.store_id(user)) def remove_suggestion(self, user, suggested_user): @@ -128,8 +133,8 @@ def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): return if instance.user_subject.local: - suggested_users.remove_suggestion(instance.user_subject, instance.user_object) - suggested_users.rerank_obj(instance.user_object) + remove_suggestion_task.delay(instance.user_subject.id, instance.user_object.id) + rerank_user_task.delay(instance.user_object.id) @receiver(signals.post_save, sender=models.UserBlocks) @@ -137,9 +142,9 @@ def update_suggestions_on_follow(sender, instance, created, *args, **kwargs): def update_suggestions_on_block(sender, instance, *args, **kwargs): """remove blocked users from recs""" if instance.user_subject.local: - suggested_users.remove_suggestion(instance.user_subject, instance.user_object) + remove_suggestion_task.delay(instance.user_subject.id, instance.user_object.id) if instance.user_object.local: - suggested_users.remove_suggestion(instance.user_object, instance.user_subject) + remove_suggestion_task.delay(instance.user_object.id, instance.user_subject.id) @receiver(signals.post_delete, sender=models.UserFollows) @@ -147,7 +152,7 @@ def update_suggestions_on_block(sender, instance, *args, **kwargs): def update_suggestions_on_unfollow(sender, instance, **kwargs): """update rankings, but don't re-suggest because it was probably intentional""" if instance.user_object.discoverable: - suggested_users.rerank_obj(instance.user_object) + rerank_user_task.delay(instance.user_object.id) @receiver(signals.post_save, sender=models.ShelfBook) @@ -157,24 +162,50 @@ def update_rank_on_shelving(sender, instance, *args, **kwargs): """when a user shelves or unshelves a book, re-compute their rank""" # if it's a local user, re-calculate who is rec'ed to them if instance.user.local: - suggested_users.rerank_user_suggestions(instance.user) + rerank_suggestions_task.delay(instance.user.id) # if the user is discoverable, update their rankings - if not instance.user.discoverable: - return - suggested_users.rerank_obj(instance.user) + if instance.user.discoverable: + rerank_user_task.delay(instance.user.id) @receiver(signals.post_save, sender=models.User) # pylint: disable=unused-argument, too-many-arguments def add_new_user(sender, instance, created, **kwargs): """a new user, wow how cool""" + # a new user is found, create suggestions for them if created and instance.local: - # a new user is found, create suggestions for them - suggested_users.rerank_user_suggestions(instance) + rerank_suggestions_task.delay(instance.id) # this happens on every save, not just when discoverability changes, annoyingly if instance.discoverable: - suggested_users.rerank_obj(instance, update_only=False) + rerank_user_task.delay(instance.id, update_only=False) elif not created: - suggested_users.remove_object_from_related_stores(instance) + remove_user_task.delay(instance.id) + + +@app.task +def rerank_suggestions_task(user_id): + """do the hard work in celery""" + suggested_users.rerank_user_suggestions(user_id) + + +@app.task +def rerank_user_task(user_id, update_only=False): + """do the hard work in celery""" + user = models.User.objects.get(id=user_id) + suggested_users.rerank_obj(user, update_only=update_only) + + +@app.task +def remove_user_task(user_id): + """do the hard work in celery""" + user = models.User.objects.get(id=user_id) + suggested_users.remove_object_from_related_stores(user) + + +@app.task +def remove_suggestion_task(user_id, suggested_user_id): + """remove a specific user from a specific user's suggestions""" + suggested_user = models.User.objects.get(id=suggested_user_id) + suggested_users.remove_suggestion(user_id, suggested_user) diff --git a/celerywyrm/celery.py b/celerywyrm/celery.py index 4af8e281d..fcf75b049 100644 --- a/celerywyrm/celery.py +++ b/celerywyrm/celery.py @@ -25,4 +25,5 @@ app.autodiscover_tasks(["bookwyrm"], related_name="connectors.abstract_connector app.autodiscover_tasks(["bookwyrm"], related_name="emailing") app.autodiscover_tasks(["bookwyrm"], related_name="goodreads_import") app.autodiscover_tasks(["bookwyrm"], related_name="models.user") +app.autodiscover_tasks(["bookwyrm"], related_name="suggested_users") app.autodiscover_tasks(["bookwyrm"], related_name="views.inbox") From 5174260351c659530b0616e82e95f74eb94f7570 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 15:57:08 -0700 Subject: [PATCH 0019/1024] Python formatting --- bookwyrm/suggested_users.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index bce3e5f13..2aee6d88b 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -47,9 +47,7 @@ class SuggestedUsers(RedisStore): def get_users_for_object(self, obj): # pylint: disable=no-self-use """given a user, who might want to follow them""" - return models.User.objects.filter( - local=True, - ).exclude( + return models.User.objects.filter(local=True,).exclude( Q(id=obj.id) | Q(followers=obj) | Q(id__in=obj.blocks.all()) | Q(blocks=obj) ) From 98e537280e74183a2c0ae4828816a3b6defc29b9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 22 May 2021 16:10:11 -0700 Subject: [PATCH 0020/1024] Adds management command for populating suggestions --- .../management/commands/populate_streams.py | 8 +---- .../commands/populate_suggestions.py | 25 +++++++++++++ bookwyrm/management/commands/ratings_bot.py | 35 +++++++++++++++++++ bw-dev | 5 ++- 4 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/management/commands/populate_suggestions.py create mode 100644 bookwyrm/management/commands/ratings_bot.py diff --git a/bookwyrm/management/commands/populate_streams.py b/bookwyrm/management/commands/populate_streams.py index 04f6bf6e2..f8aa21a52 100644 --- a/bookwyrm/management/commands/populate_streams.py +++ b/bookwyrm/management/commands/populate_streams.py @@ -1,12 +1,6 @@ """ Re-create user streams """ from django.core.management.base import BaseCommand -import redis - -from bookwyrm import activitystreams, models, settings - -r = redis.Redis( - host=settings.REDIS_ACTIVITY_HOST, port=settings.REDIS_ACTIVITY_PORT, db=0 -) +from bookwyrm import activitystreams, models def populate_streams(): diff --git a/bookwyrm/management/commands/populate_suggestions.py b/bookwyrm/management/commands/populate_suggestions.py new file mode 100644 index 000000000..32495497e --- /dev/null +++ b/bookwyrm/management/commands/populate_suggestions.py @@ -0,0 +1,25 @@ +""" Populate suggested users """ +from django.core.management.base import BaseCommand + +from bookwyrm import models +from bookwyrm.suggested_users import rerank_suggestions_task + + +def populate_suggestions(): + """build all the streams for all the users""" + users = models.User.objects.filter( + local=True, + is_active=True, + ).values_list("id", flat=True) + for user in users: + rerank_suggestions_task.delay(user) + + +class Command(BaseCommand): + """start all over with user suggestions""" + + help = "Populate suggested users for all users" + # pylint: disable=no-self-use,unused-argument + def handle(self, *args, **options): + """run builder""" + populate_suggestions() diff --git a/bookwyrm/management/commands/ratings_bot.py b/bookwyrm/management/commands/ratings_bot.py new file mode 100644 index 000000000..57cd84999 --- /dev/null +++ b/bookwyrm/management/commands/ratings_bot.py @@ -0,0 +1,35 @@ +""" we have the goodreads ratings......... """ +from datetime import datetime +from django.core.management.base import BaseCommand +from django.utils import timezone +from bookwyrm import models + + +def get_ratings(): + """find and set ratings based on goodreads import lines""" + import_items = models.ImportItem.objects.filter(book__isnull=False).all() + user = models.User.objects.get(localname="goodreads-average-ratings") + for item in import_items: + rating = item.data.get("Average Rating") + if ( + not rating + or models.ReviewRating.objects.filter(user=user, book=item.book).exists() + ): + continue + models.ReviewRating.objects.create( + user=user, + rating=float(rating), + book=item.book.edition, + published_date=timezone.make_aware(datetime(2000, 1, 1)), # long ago + privacy="followers", + ) + + +class Command(BaseCommand): + """dedplucate allllll the book data models""" + + help = "merges duplicate book data" + # pylint: disable=no-self-use,unused-argument + def handle(self, *args, **options): + """run deudplications""" + get_ratings() diff --git a/bw-dev b/bw-dev index c2b63bc17..0b583083c 100755 --- a/bw-dev +++ b/bw-dev @@ -107,7 +107,10 @@ case "$CMD" in populate_streams) runweb python manage.py populate_streams ;; + populate_suggestions) + runweb python manage.py populate_suggestions + ;; *) - echo "Unrecognised command. Try: build, clean, up, initdb, resetdb, makemigrations, migrate, bash, shell, dbshell, restart_celery, test, pytest, test_report, black, populate_feeds" + echo "Unrecognised command. Try: build, clean, up, initdb, resetdb, makemigrations, migrate, bash, shell, dbshell, restart_celery, test, pytest, test_report, black, populate_streams, populate_suggestions" ;; esac From ff95a709a8bfca6a39df8f4cd6c9d6de45ac7241 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:14:21 +0200 Subject: [PATCH 0021/1024] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index cf88e9878..74eebb96b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ #nginx nginx/default.conf + +#macOS +.DS_Store From 77e81c4dbbf9180cad5e62aab05b3674e0d782f2 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:14:51 +0200 Subject: [PATCH 0022/1024] Add django-imagekit to BookWyrm --- bookwyrm/settings.py | 1 + bw-dev | 5 ++++- requirements.txt | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index d694e33fd..b1deed8fb 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -62,6 +62,7 @@ INSTALLED_APPS = [ "django_rename_app", "bookwyrm", "celery", + "imagekit", ] MIDDLEWARE = [ diff --git a/bw-dev b/bw-dev index c2b63bc17..1dd4c0ff7 100755 --- a/bw-dev +++ b/bw-dev @@ -107,7 +107,10 @@ case "$CMD" in populate_streams) runweb python manage.py populate_streams ;; + generateimages) + runweb python manage.py generateimages + ;; *) - echo "Unrecognised command. Try: build, clean, up, initdb, resetdb, makemigrations, migrate, bash, shell, dbshell, restart_celery, test, pytest, test_report, black, populate_feeds" + echo "Unrecognised command. Try: build, clean, up, initdb, resetdb, makemigrations, migrate, bash, shell, dbshell, restart_celery, test, pytest, test_report, black, populate_feeds, generateimages" ;; esac diff --git a/requirements.txt b/requirements.txt index 289d6fe68..7a458094e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ celery==4.4.2 Django==3.2.0 +django-imagekit==4.0.2 django-model-utils==4.0.0 environs==7.2.0 flower==0.9.4 From f60e9d76d264e042bad39cf84025728bf512e919 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:15:08 +0200 Subject: [PATCH 0023/1024] Generate generators --- bookwyrm/imagegenerators.py | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 bookwyrm/imagegenerators.py diff --git a/bookwyrm/imagegenerators.py b/bookwyrm/imagegenerators.py new file mode 100644 index 000000000..bad9028e5 --- /dev/null +++ b/bookwyrm/imagegenerators.py @@ -0,0 +1,75 @@ +from imagekit import ImageSpec, register +from imagekit.processors import ResizeToFit + +class BookXSmallWebp(ImageSpec): + processors = [ResizeToFit(80, 80)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookXSmallJpg(ImageSpec): + processors = [ResizeToFit(80, 80)] + format = 'JPEG' + options = { 'quality': 95 } + +class BookSmallWebp(ImageSpec): + processors = [ResizeToFit(100, 100)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookSmallJpg(ImageSpec): + processors = [ResizeToFit(100, 100)] + format = 'JPEG' + options = { 'quality': 95 } + +class BookMediumWebp(ImageSpec): + processors = [ResizeToFit(150, 150)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookMediumJpg(ImageSpec): + processors = [ResizeToFit(150, 150)] + format = 'JPEG' + options = { 'quality': 95 } + +class BookLargeWebp(ImageSpec): + processors = [ResizeToFit(200, 200)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookLargeJpg(ImageSpec): + processors = [ResizeToFit(200, 200)] + format = 'JPEG' + options = { 'quality': 95 } + +class BookXLargeWebp(ImageSpec): + processors = [ResizeToFit(250, 250)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookXLargeJpg(ImageSpec): + processors = [ResizeToFit(250, 250)] + format = 'JPEG' + options = { 'quality': 95 } + +class BookXxLargeWebp(ImageSpec): + processors = [ResizeToFit(500, 500)] + format = 'WEBP' + options = { 'quality': 95 } + +class BookXxLargeJpg(ImageSpec): + processors = [ResizeToFit(500, 500)] + format = 'JPEG' + options = { 'quality': 95 } + +register.generator('bw:book:xsmall:webp', BookXSmallWebp) +register.generator('bw:book:xsmall:jpg', BookXSmallJpg) +register.generator('bw:book:small:webp', BookSmallWebp) +register.generator('bw:book:small:jpg', BookSmallJpg) +register.generator('bw:book:medium:webp', BookMediumWebp) +register.generator('bw:book:medium:jpg', BookMediumJpg) +register.generator('bw:book:large:webp', BookLargeWebp) +register.generator('bw:book:large:jpg', BookLargeJpg) +register.generator('bw:book:xlarge:webp', BookXLargeWebp) +register.generator('bw:book:xlarge:jpg', BookXLargeJpg) +register.generator('bw:book:xxlarge:webp', BookXxLargeWebp) +register.generator('bw:book:xxlarge:jpg', BookXxLargeJpg) From 4c55f07f2ab17cde6e95fdb699063afcedb0ff50 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:16:09 +0200 Subject: [PATCH 0024/1024] Update book_cover.html --- bookwyrm/templates/snippets/book_cover.html | 153 ++++++++++++++++---- 1 file changed, 128 insertions(+), 25 deletions(-) diff --git a/bookwyrm/templates/snippets/book_cover.html b/bookwyrm/templates/snippets/book_cover.html index 16ab305e5..6a15f0fd4 100644 --- a/bookwyrm/templates/snippets/book_cover.html +++ b/bookwyrm/templates/snippets/book_cover.html @@ -1,41 +1,144 @@ {% spaceless %} {% load i18n %} +{% load imagekit %} -
+ {% with external_path|yesno:',/images/' as image_path %} - {% if not book.cover %} - no-cover + {% if size_mobile == 'xsmall' %} + {% generateimage 'bw:book:xsmall:webp' source=book.cover as th_xsmall_webp %} + {% generateimage 'bw:book:xsmall:jpg' source=book.cover as th_xsmall_jpg %} + + + {% elif size_mobile == 'small' %} + {% generateimage 'bw:book:small:webp' source=book.cover as th_small_webp %} + {% generateimage 'bw:book:small:jpg' source=book.cover as th_small_jpg %} + + + {% elif size_mobile == 'medium' %} + {% generateimage 'bw:book:medium:webp' source=book.cover as th_medium_webp %} + {% generateimage 'bw:book:medium:jpg' source=book.cover as th_medium_jpg %} + + + {% elif size_mobile == 'large' %} + {% generateimage 'bw:book:large:webp' source=book.cover as th_large_webp %} + {% generateimage 'bw:book:large:jpg' source=book.cover as th_large_jpg %} + + + {% elif size_mobile == 'xlarge' %} + {% generateimage 'bw:book:xlarge:webp' source=book.cover as th_xlarge_webp %} + {% generateimage 'bw:book:xlarge:jpg' source=book.cover as th_xlarge_jpg %} + + + {% elif size_mobile == 'xxlarge' %} + {% generateimage 'bw:book:xxlarge:webp' source=book.cover as th_xxlarge_webp %} + {% generateimage 'bw:book:xxlarge:jpg' source=book.cover as th_xxlarge_jpg %} + + {% endif %} - " - {% if book.alt_text %} - title="{{ book.alt_text }}" - {% endif %} -> - + + {% elif size == 'small' %} + {% generateimage 'bw:book:small:webp' source=book.cover as th_small_webp %} + {% generateimage 'bw:book:small:jpg' source=book.cover as th_small_jpg %} + + + {% elif size == 'medium' %} + {% generateimage 'bw:book:medium:webp' source=book.cover as th_medium_webp %} + {% generateimage 'bw:book:medium:jpg' source=book.cover as th_medium_jpg %} + + + {% elif size == 'large' %} + {% generateimage 'bw:book:large:webp' source=book.cover as th_large_webp %} + {% generateimage 'bw:book:large:jpg' source=book.cover as th_large_jpg %} + + + {% elif size == 'xlarge' %} + {% generateimage 'bw:book:xlarge:webp' source=book.cover as th_xlarge_webp %} + {% generateimage 'bw:book:xlarge:jpg' source=book.cover as th_xlarge_jpg %} + + + {% elif size == 'xxlarge' %} + {% generateimage 'bw:book:xxlarge:webp' source=book.cover as th_xxlarge_webp %} + {% generateimage 'bw:book:xxlarge:jpg' source=book.cover as th_xxlarge_jpg %} + + + {% endif %} - {% if book.cover %} - src="{% if img_path is None %}/images/{% else %}{{ img_path }}{% endif %}{{ book.cover }}" + {{ book.alt_text|default:'' }} + {% endwith %} + +{% endif %} - {% if book.alt_text %} - alt="{{ book.alt_text }}" - {% endif %} - {% else %} +{% if not book.cover and book.alt_text %} +
+ {% trans - - {% if not book.cover and book.alt_text %}
+ >

{{ book.alt_text }}

- {% endif %} -
+
+{% endif %} {% endspaceless %} From c1456ce8531d9243ab2d68c430e4a791d374d88a Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:16:33 +0200 Subject: [PATCH 0025/1024] Update .cover-caption name and styles --- bookwyrm/static/css/bookwyrm.css | 9 +++++++-- bookwyrm/templates/snippets/book_cover.html | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 3db25d1fe..5a4495c1e 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -219,16 +219,21 @@ body { /* Cover caption * -------------------------------------------------------------------------- */ -.no-cover .cover_caption { +.no-cover .cover-caption { position: absolute; top: 0; right: 0; bottom: 0; left: 0; - padding: 0.25em; + padding: 0.5em; font-size: 0.75em; color: white; background-color: #002549; + display: flex; + align-items: center; + justify-content: center; + white-space: initial; + text-align: center; } /** Avatars diff --git a/bookwyrm/templates/snippets/book_cover.html b/bookwyrm/templates/snippets/book_cover.html index 6a15f0fd4..fd1fb438a 100644 --- a/bookwyrm/templates/snippets/book_cover.html +++ b/bookwyrm/templates/snippets/book_cover.html @@ -135,8 +135,8 @@ class="book-cover" src="/static/images/no_cover.jpg" alt="{% trans "No cover" %}" -
> +

{{ book.alt_text }}

From dc494323221729d7e06389d1df2f7c6f04ea3325 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:17:39 +0200 Subject: [PATCH 0026/1024] Change img_path to external_path --- bookwyrm/templates/snippets/search_result_text.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/search_result_text.html b/bookwyrm/templates/snippets/search_result_text.html index e39d34104..a18b125f7 100644 --- a/bookwyrm/templates/snippets/search_result_text.html +++ b/bookwyrm/templates/snippets/search_result_text.html @@ -1,7 +1,7 @@ {% load i18n %}
- {% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' img_path=false %} + {% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' external_path=True %}
From 36f447210a20e0dde7bb1f86fc27e1f86ec5972e Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 24 May 2021 16:18:05 +0200 Subject: [PATCH 0027/1024] Specify sizes on all templates --- bookwyrm/templates/book/book.html | 2 +- bookwyrm/templates/book/edit_book.html | 2 +- bookwyrm/templates/book/editions.html | 2 +- bookwyrm/templates/discover/large-book.html | 2 +- bookwyrm/templates/discover/small-book.html | 2 +- bookwyrm/templates/get_started/book_preview.html | 2 +- bookwyrm/templates/import_status.html | 2 +- bookwyrm/templates/lists/curate.html | 2 +- bookwyrm/templates/lists/list.html | 4 ++-- bookwyrm/templates/lists/list_items.html | 2 +- bookwyrm/templates/snippets/status/content_status.html | 2 +- bookwyrm/templates/snippets/status/generated_status.html | 2 +- bookwyrm/templates/user/shelf/shelf.html | 2 +- bookwyrm/templates/user/user.html | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index df76d8e11..b1b893b7d 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -45,7 +45,7 @@
- {% include 'snippets/book_cover.html' with book=book cover_class='is-h-m-mobile' %} + {% include 'snippets/book_cover.html' with size='xxlarge' size_mobile='medium' book=book cover_class='is-h-m-mobile' %} {% include 'snippets/rate_action.html' with user=request.user book=book %}
diff --git a/bookwyrm/templates/book/edit_book.html b/bookwyrm/templates/book/edit_book.html index 8dae1d044..0736eabcf 100644 --- a/bookwyrm/templates/book/edit_book.html +++ b/bookwyrm/templates/book/edit_book.html @@ -183,7 +183,7 @@

{% trans "Cover" %}

- {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xl-mobile is-w-auto-tablet' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xl-mobile is-w-auto-tablet' size_mobile='xlarge' size='large' %}
diff --git a/bookwyrm/templates/book/editions.html b/bookwyrm/templates/book/editions.html index 0d5c10447..d22dd71a7 100644 --- a/bookwyrm/templates/book/editions.html +++ b/bookwyrm/templates/book/editions.html @@ -15,7 +15,7 @@
diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index 93026991e..2f99a75a1 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -9,7 +9,7 @@ {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} + >{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' size='xlarge' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %}
diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html index 73133de45..82cd4a7ee 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/discover/small-book.html @@ -5,7 +5,7 @@ {% if book %} {% with book=book %} - {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %} + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' size='large' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} diff --git a/bookwyrm/templates/get_started/book_preview.html b/bookwyrm/templates/get_started/book_preview.html index d8941ad50..893e7593a 100644 --- a/bookwyrm/templates/get_started/book_preview.html +++ b/bookwyrm/templates/get_started/book_preview.html @@ -1,6 +1,6 @@ {% load i18n %}
- {% include 'snippets/book_cover.html' with book=book cover_class='is-h-l is-h-m-mobile' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-h-l is-h-m-mobile' size_mobile='medium' size='large' %}
- - - - From 9bbdde1597299c3bdb7d9cf204f3a18324503e4d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 10:58:23 -0700 Subject: [PATCH 0082/1024] Python formatting --- .../0046_user_default_post_privacy.py | 17 +++++++++++++---- bookwyrm/migrations/0079_merge_20210804_1746.py | 7 +++---- bookwyrm/models/user.py | 5 ++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/bookwyrm/migrations/0046_user_default_post_privacy.py b/bookwyrm/migrations/0046_user_default_post_privacy.py index 3f2254726..f1c8e7c31 100644 --- a/bookwyrm/migrations/0046_user_default_post_privacy.py +++ b/bookwyrm/migrations/0046_user_default_post_privacy.py @@ -6,13 +6,22 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0045_auto_20210210_2114'), + ("bookwyrm", "0045_auto_20210210_2114"), ] operations = [ migrations.AddField( - model_name='user', - name='default_post_privacy', - field=models.CharField(choices=[('public', 'Public'), ('unlisted', 'Unlisted'), ('followers', 'Followers'), ('direct', 'Direct')], default='public', max_length=255), + model_name="user", + name="default_post_privacy", + field=models.CharField( + choices=[ + ("public", "Public"), + ("unlisted", "Unlisted"), + ("followers", "Followers"), + ("direct", "Direct"), + ], + default="public", + max_length=255, + ), ), ] diff --git a/bookwyrm/migrations/0079_merge_20210804_1746.py b/bookwyrm/migrations/0079_merge_20210804_1746.py index 315733a3f..ed5d50d0b 100644 --- a/bookwyrm/migrations/0079_merge_20210804_1746.py +++ b/bookwyrm/migrations/0079_merge_20210804_1746.py @@ -6,9 +6,8 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0046_user_default_post_privacy'), - ('bookwyrm', '0078_add_shelved_date'), + ("bookwyrm", "0046_user_default_post_privacy"), + ("bookwyrm", "0078_add_shelved_date"), ] - operations = [ - ] + operations = [] diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 33102f98b..21b6bbaac 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -26,6 +26,7 @@ from .base_model import BookWyrmModel, DeactivationReason from .federated_server import FederatedServer from . import fields, Review + class User(OrderedCollectionPageMixin, AbstractUser): """a user who wants to read books""" @@ -105,9 +106,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): related_name="favorite_statuses", ) default_post_privacy = models.CharField( - max_length=255, - default='public', - choices=fields.PrivacyLevels.choices + max_length=255, default="public", choices=fields.PrivacyLevels.choices ) remote_id = fields.RemoteIdField(null=True, unique=True, activitypub_field="id") created_date = models.DateTimeField(auto_now_add=True) From 392eb83bb34de869407d4afca2bae18f9b15af0b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 11:30:23 -0700 Subject: [PATCH 0083/1024] Fixes edit user view tests --- bookwyrm/tests/views/test_edit_user.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/tests/views/test_edit_user.py b/bookwyrm/tests/views/test_edit_user.py index 0a86c486a..ccfb4c90d 100644 --- a/bookwyrm/tests/views/test_edit_user.py +++ b/bookwyrm/tests/views/test_edit_user.py @@ -62,6 +62,7 @@ class EditUserViews(TestCase): form = forms.EditUserForm(instance=self.local_user) form.data["name"] = "New Name" form.data["email"] = "wow@email.com" + form.data["default_post_privacy"] = "public" form.data["preferred_timezone"] = "UTC" request = self.factory.post("", form.data) request.user = self.local_user @@ -81,6 +82,7 @@ class EditUserViews(TestCase): form = forms.EditUserForm(instance=self.local_user) form.data["name"] = "New Name" form.data["email"] = "wow@email.com" + form.data["default_post_privacy"] = "public" form.data["preferred_timezone"] = "UTC" image_file = pathlib.Path(__file__).parent.joinpath( "../../static/images/no_cover.jpg" From 535ff5e6d8ceb8ed68a8105a8a4cd94aa6fcc571 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 12:05:24 -0700 Subject: [PATCH 0084/1024] Handle goal pages for unset years --- bookwyrm/templates/goal.html | 4 ++-- bookwyrm/views/goal.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/goal.html b/bookwyrm/templates/goal.html index 134f419fc..b285eec43 100644 --- a/bookwyrm/templates/goal.html +++ b/bookwyrm/templates/goal.html @@ -17,9 +17,9 @@ {% block panel %}
- {% if user == request.user %} + {% now 'Y' as current_year %} + {% if user == request.user and year == current_year %}
- {% now 'Y' as year %}

diff --git a/bookwyrm/views/goal.py b/bookwyrm/views/goal.py index 84091fe35..80b6af3cf 100644 --- a/bookwyrm/views/goal.py +++ b/bookwyrm/views/goal.py @@ -4,6 +4,7 @@ from django.http import HttpResponseNotFound from django.shortcuts import redirect from django.template.loader import get_template from django.template.response import TemplateResponse +from django.utils import timezone from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.http import require_POST @@ -26,6 +27,10 @@ class Goal(View): if not goal and user != request.user: return HttpResponseNotFound() + current_year = timezone.now().year + if not goal and year != timezone.now().year: + return redirect('user-goal', username, current_year) + if goal and not goal.visible_to_user(request.user): return HttpResponseNotFound() From a679a46bcac0bbc06348cf5acda43b203a78701c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 12:36:54 -0700 Subject: [PATCH 0085/1024] Limit authors displayed in status --- bookwyrm/templates/snippets/authors.html | 19 +++++++++++++++++-- bookwyrm/templates/snippets/book_titleby.html | 9 ++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/snippets/authors.html b/bookwyrm/templates/snippets/authors.html index 476956b6e..5584417d9 100644 --- a/bookwyrm/templates/snippets/authors.html +++ b/bookwyrm/templates/snippets/authors.html @@ -1,9 +1,16 @@ {% spaceless %} +{% load i18n %} +{% load humanize %} {% comment %} @todo The author property needs to be an Organization or a Person. We’ll be using Thing which is the more generic ancestor. @see https://schema.org/Author {% endcomment %} -{% for author in book.authors.all %} +{% firstof limit None as limit %} +{% with subtraction_value='-'|add:limit %} +{% with remainder_count=book.authors.count|add:subtraction_value %} +{% with remainder_count_display=remainder_count|intcomma %} + +{% for author in book.authors.all|slice:limit %} {{ author.name }}{% if not forloop.last %}, {% endif %} + >{{ author.name }}{% if not forloop.last %}, {% elif remainder_count > 0 %}, {% blocktrans trimmed count counter=remainder_count %} +and {{ remainder_count_display }} other +{% plural %} +and {{ remainder_count_display }} others +{% endblocktrans %}{% endif %} {% endfor %} + +{% endwith %} +{% endwith %} +{% endwith %} {% endspaceless %} diff --git a/bookwyrm/templates/snippets/book_titleby.html b/bookwyrm/templates/snippets/book_titleby.html index 353f9d12e..5eddabff7 100644 --- a/bookwyrm/templates/snippets/book_titleby.html +++ b/bookwyrm/templates/snippets/book_titleby.html @@ -1,8 +1,15 @@ {% load i18n %} {% load utilities %} +{% spaceless %} + {% if book.authors %} -{% blocktrans with path=book.local_path title=book|book_title %}{{ title }} by {% endblocktrans %}{% include 'snippets/authors.html' with book=book %} +{% blocktrans trimmed with path=book.local_path title=book|book_title %} +{{ title }} by +{% endblocktrans %} +{% include 'snippets/authors.html' with book=book limit=3 %} + {% else %} {{ book|book_title }} {% endif %} +{% endspaceless %} From 12fb9698211945c6545c05225ef47d85f0d8cdf7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 12:40:15 -0700 Subject: [PATCH 0086/1024] Python formatting --- bookwyrm/views/goal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/goal.py b/bookwyrm/views/goal.py index 80b6af3cf..122245179 100644 --- a/bookwyrm/views/goal.py +++ b/bookwyrm/views/goal.py @@ -29,7 +29,7 @@ class Goal(View): current_year = timezone.now().year if not goal and year != timezone.now().year: - return redirect('user-goal', username, current_year) + return redirect("user-goal", username, current_year) if goal and not goal.visible_to_user(request.user): return HttpResponseNotFound() From 54f6da238265aacdbe45f97c248091f804e75c66 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 12:59:06 -0700 Subject: [PATCH 0087/1024] Use current year in goal tests --- bookwyrm/tests/views/test_goal.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bookwyrm/tests/views/test_goal.py b/bookwyrm/tests/views/test_goal.py index ad615ba6e..23bd8e1a8 100644 --- a/bookwyrm/tests/views/test_goal.py +++ b/bookwyrm/tests/views/test_goal.py @@ -39,6 +39,7 @@ class GoalViews(TestCase): ) self.anonymous_user = AnonymousUser self.anonymous_user.is_authenticated = False + self.year = timezone.now().year models.SiteSettings.objects.create() def test_goal_page_no_goal(self): @@ -47,7 +48,7 @@ class GoalViews(TestCase): request = self.factory.get("") request.user = self.rat - result = view(request, self.local_user.localname, 2020) + result = view(request, self.local_user.localname, self.year) self.assertEqual(result.status_code, 404) def test_goal_page_no_goal_self(self): @@ -56,7 +57,7 @@ class GoalViews(TestCase): request = self.factory.get("") request.user = self.local_user - result = view(request, self.local_user.localname, 2020) + result = view(request, self.local_user.localname, self.year) result.render() self.assertIsInstance(result, TemplateResponse) @@ -66,7 +67,7 @@ class GoalViews(TestCase): request = self.factory.get("") request.user = self.anonymous_user - result = view(request, self.local_user.localname, 2020) + result = view(request, self.local_user.localname, self.year) self.assertEqual(result.status_code, 302) def test_goal_page_public(self): @@ -94,13 +95,13 @@ class GoalViews(TestCase): def test_goal_page_private(self): """view a user's private goal""" models.AnnualGoal.objects.create( - user=self.local_user, year=2020, goal=15, privacy="followers" + user=self.local_user, year=self.year, goal=15, privacy="followers" ) view = views.Goal.as_view() request = self.factory.get("") request.user = self.rat - result = view(request, self.local_user.localname, 2020) + result = view(request, self.local_user.localname, self.year) self.assertEqual(result.status_code, 404) @patch("bookwyrm.activitystreams.ActivityStream.add_status") @@ -112,19 +113,19 @@ class GoalViews(TestCase): { "user": self.local_user.id, "goal": 10, - "year": 2020, + "year": self.year, "privacy": "unlisted", "post-status": True, }, ) request.user = self.local_user with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request, self.local_user.localname, 2020) + view(request, self.local_user.localname, self.year) goal = models.AnnualGoal.objects.get() self.assertEqual(goal.user, self.local_user) self.assertEqual(goal.goal, 10) - self.assertEqual(goal.year, 2020) + self.assertEqual(goal.year, self.year) self.assertEqual(goal.privacy, "unlisted") status = models.GeneratedNote.objects.get() From f5c129dce732032a1daee5ba1be1c1a3dac1fd53 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 13:38:06 -0700 Subject: [PATCH 0088/1024] Also in suggestion area --- bookwyrm/templates/directory/user_card.html | 9 ++++++++- .../templates/snippets/suggested_users.html | 17 +++++++++++++++-- bookwyrm/templates/user/user_preview.html | 15 ++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/directory/user_card.html b/bookwyrm/templates/directory/user_card.html index b7941826b..ccae925a1 100644 --- a/bookwyrm/templates/directory/user_card.html +++ b/bookwyrm/templates/directory/user_card.html @@ -11,7 +11,14 @@
- {{ user.display_name }} + + {{ user.display_name }} + {% if user.manually_approves_followers %} + + {% trans "Locked account" %} + + {% endif %} + @{{ user|username }} {% include 'snippets/follow_button.html' with user=user %} diff --git a/bookwyrm/templates/snippets/suggested_users.html b/bookwyrm/templates/snippets/suggested_users.html index eb146f7eb..4a757ef0c 100644 --- a/bookwyrm/templates/snippets/suggested_users.html +++ b/bookwyrm/templates/snippets/suggested_users.html @@ -13,10 +13,23 @@ {% include 'snippets/follow_button.html' with user=user minimal=True %} {% if user.mutuals %}

- {% blocktrans with mutuals=user.mutuals|intcomma count counter=user.mutuals %}{{ mutuals }} follower you follow{% plural %}{{ mutuals }} followers you follow{% endblocktrans %} + {% blocktrans trimmed with mutuals=user.mutuals|intcomma count counter=user.mutuals %} + {{ mutuals }} follower you follow + {% plural %} + {{ mutuals }} followers you follow{% endblocktrans %}

{% elif user.shared_books %} -

{% blocktrans with shared_books=user.shared_books|intcomma count counter=user.shared_books %}{{ shared_books }} book on your shelves{% plural %}{{ shared_books }} books on your shelves{% endblocktrans %}

+

+ {% blocktrans trimmed with shared_books=user.shared_books|intcomma count counter=user.shared_books %} + {{ shared_books }} book on your shelves + {% plural %} + {{ shared_books }} books on your shelves + {% endblocktrans %} +

+ {% elif request.user in user.following.all %} +

+ {% trans "Follows you" %} +

{% endif %}

diff --git a/bookwyrm/templates/user/user_preview.html b/bookwyrm/templates/user/user_preview.html index 22d44c878..c6b3ea842 100644 --- a/bookwyrm/templates/user/user_preview.html +++ b/bookwyrm/templates/user/user_preview.html @@ -10,7 +10,14 @@
-

{% if user.name %}{{ user.name }}{% else %}{{ user.localname }}{% endif %}

+

+ {% if user.name %}{{ user.name }}{% else %}{{ user.localname }}{% endif %} + {% if user.manually_approves_followers %} + + {% trans "Locked account" %} + + {% endif %} +

{{ user.username }}

{% blocktrans with date=user.created_date|naturaltime %}Joined {{ date }}{% endblocktrans %}

@@ -23,7 +30,13 @@ {% mutuals_count user as mutuals %} + {% if mutuals %} {% blocktrans with mutuals_display=mutuals|intcomma count counter=mutuals %}{{ mutuals_display }} follower you follow{% plural %}{{ mutuals_display }} followers you follow{% endblocktrans %} + {% elif request.user in user.following.all %} + {% trans "Follows you" %} + {% else %} + {% trans "No followers you follow" %} + {% endif %} {% endif %} From aabac4e7b7b4aa28273d2188e176becb5b06a9c0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 13:42:34 -0700 Subject: [PATCH 0089/1024] Updates translations --- locale/de_DE/LC_MESSAGES/django.mo | Bin 24354 -> 24293 bytes locale/de_DE/LC_MESSAGES/django.po | 683 +++++++++++++++----------- locale/en_US/LC_MESSAGES/django.po | 654 ++++++++++++++----------- locale/es/LC_MESSAGES/django.mo | Bin 43363 -> 43107 bytes locale/es/LC_MESSAGES/django.po | 687 ++++++++++++++++----------- locale/fr_FR/LC_MESSAGES/django.po | 505 ++++++++++++-------- locale/zh_Hans/LC_MESSAGES/django.po | 343 +++++++------ locale/zh_Hant/LC_MESSAGES/django.po | 682 +++++++++++++++----------- 8 files changed, 2057 insertions(+), 1497 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index dde00be621032b841673a440278b1fb305361245..fb15184108c67c333088d8b27062a76939709a84 100644 GIT binary patch delta 7310 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 F0|4Co+eiQa delta 7368 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 E0LDz~D*ylh diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 3125d147c..5edf43d68 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-06 20:52+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,109 +18,113 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:224 +#: bookwyrm/forms.py:232 #, fuzzy #| msgid "A user with that username already exists." msgid "A user with this email already exists." msgstr "Dieser Benutzename ist bereits vergeben." -#: bookwyrm/forms.py:238 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "Ein Tag" -#: bookwyrm/forms.py:239 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "Eine Woche" -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "Ein Monat" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "Läuft nicht aus" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d Benutzungen" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:257 #, fuzzy #| msgid "Unlisted" msgid "Unlimited" msgstr "Ungelistet" -#: bookwyrm/forms.py:299 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:300 +#: bookwyrm/forms.py:308 #, fuzzy #| msgid "Title" msgid "Book Title" msgstr "Titel" -#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: 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:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:315 #, fuzzy #| msgid "Started reading" msgid "Ascending" msgstr "Zu lesen angefangen" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:316 #, fuzzy #| msgid "Started reading" msgid "Descending" msgstr "Zu lesen angefangen" -#: bookwyrm/models/fields.py:25 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "%(value)s ist keine gültige remote_id" -#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "%(value)s ist kein gültiger Username" -#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "Username" -#: bookwyrm/models/fields.py:171 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "Dieser Benutzename ist bereits vergeben." -#: bookwyrm/settings.py:156 +#: bookwyrm/settings.py:166 msgid "English" msgstr "Englisch" -#: bookwyrm/settings.py:157 +#: bookwyrm/settings.py:167 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:158 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "Spanisch" -#: bookwyrm/settings.py:159 +#: bookwyrm/settings.py:169 msgid "French" msgstr "Französisch" -#: bookwyrm/settings.py:160 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "Vereinfachtes Chinesisch" +#: bookwyrm/settings.py:171 +msgid "Traditional Chinese" +msgstr "" + #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" msgstr "Nicht gefunden" @@ -146,36 +150,46 @@ msgstr "Etwas lief schief. Entschuldigung!" msgid "Edit Author" msgstr "Autor*in editieren" -#: bookwyrm/templates/author/author.html:32 -#: bookwyrm/templates/author/edit_author.html:38 +#: bookwyrm/templates/author/author.html:34 +#: bookwyrm/templates/author/edit_author.html:41 msgid "Aliases:" msgstr "" -#: bookwyrm/templates/author/author.html:38 +#: bookwyrm/templates/author/author.html:45 msgid "Born:" msgstr "" -#: bookwyrm/templates/author/author.html:44 +#: bookwyrm/templates/author/author.html:52 msgid "Died:" msgstr "" -#: bookwyrm/templates/author/author.html:51 +#: bookwyrm/templates/author/author.html:61 msgid "Wikipedia" msgstr "" -#: bookwyrm/templates/author/author.html:55 -#: bookwyrm/templates/book/book.html:78 +#: bookwyrm/templates/author/author.html:69 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "In OpenLibrary ansehen" -#: bookwyrm/templates/author/author.html:60 -#: bookwyrm/templates/book/book.html:81 +#: bookwyrm/templates/author/author.html:77 +#: bookwyrm/templates/book/book.html:98 #, fuzzy #| msgid "View on OpenLibrary" msgid "View on Inventaire" msgstr "In OpenLibrary ansehen" -#: bookwyrm/templates/author/author.html:74 +#: bookwyrm/templates/author/author.html:85 +#, fuzzy +#| msgid "View on OpenLibrary" +msgid "View on LibraryThing" +msgstr "In OpenLibrary ansehen" + +#: bookwyrm/templates/author/author.html:93 +msgid "View on Goodreads" +msgstr "" + +#: bookwyrm/templates/author/author.html:108 #, python-format msgid "Books by %(name)s" msgstr "Bücher von %(name)s" @@ -187,232 +201,232 @@ msgid "Edit Author:" msgstr "Autor*in editieren" #: bookwyrm/templates/author/edit_author.html:13 -#: bookwyrm/templates/book/edit_book.html:18 +#: bookwyrm/templates/book/edit_book.html:19 msgid "Added:" msgstr "Hinzugefügt:" #: bookwyrm/templates/author/edit_author.html:14 -#: bookwyrm/templates/book/edit_book.html:19 +#: bookwyrm/templates/book/edit_book.html:24 msgid "Updated:" msgstr "Aktualisiert:" #: bookwyrm/templates/author/edit_author.html:15 -#: bookwyrm/templates/book/edit_book.html:20 +#: bookwyrm/templates/book/edit_book.html:30 msgid "Last edited by:" msgstr "Zuletzt bearbeitet von:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:90 +#: bookwyrm/templates/book/edit_book.html:117 msgid "Metadata" msgstr "Metadaten" -#: bookwyrm/templates/author/edit_author.html:32 +#: bookwyrm/templates/author/edit_author.html:33 #: bookwyrm/templates/lists/form.html:8 #: bookwyrm/templates/user/shelf/create_shelf_form.html:13 #: bookwyrm/templates/user/shelf/edit_shelf_form.html:14 msgid "Name:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:40 -#: bookwyrm/templates/book/edit_book.html:132 -#: bookwyrm/templates/book/edit_book.html:141 -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/author/edit_author.html:43 +#: bookwyrm/templates/book/edit_book.html:162 +#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:214 #, fuzzy #| msgid "Separate multiple publishers with commas." msgid "Separate multiple values with commas." msgstr "Mehrere Herausgeber:innen durch Kommata trennen" -#: bookwyrm/templates/author/edit_author.html:46 +#: bookwyrm/templates/author/edit_author.html:50 msgid "Bio:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:51 +#: bookwyrm/templates/author/edit_author.html:57 msgid "Wikipedia link:" msgstr "Wikipedialink:" -#: bookwyrm/templates/author/edit_author.html:57 +#: bookwyrm/templates/author/edit_author.html:63 msgid "Birth date:" msgstr "Geburtsdatum:" -#: bookwyrm/templates/author/edit_author.html:65 +#: bookwyrm/templates/author/edit_author.html:71 msgid "Death date:" msgstr "Todesdatum:" -#: bookwyrm/templates/author/edit_author.html:73 +#: bookwyrm/templates/author/edit_author.html:79 msgid "Author Identifiers" msgstr "Autor*innenidentifikatoren" -#: bookwyrm/templates/author/edit_author.html:74 +#: bookwyrm/templates/author/edit_author.html:81 msgid "Openlibrary key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:79 -#: bookwyrm/templates/book/edit_book.html:243 +#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/book/edit_book.html:293 #, fuzzy #| msgid "View on OpenLibrary" msgid "Inventaire ID:" msgstr "In OpenLibrary ansehen" -#: bookwyrm/templates/author/edit_author.html:84 +#: bookwyrm/templates/author/edit_author.html:97 msgid "Librarything key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/author/edit_author.html:105 msgid "Goodreads key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:98 -#: bookwyrm/templates/book/book.html:124 -#: bookwyrm/templates/book/edit_book.html:263 +#: bookwyrm/templates/author/edit_author.html:116 +#: bookwyrm/templates/book/book.html:141 +#: bookwyrm/templates/book/edit_book.html:321 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: 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 -#: bookwyrm/templates/snippets/readthrough.html:77 +#: bookwyrm/templates/settings/site.html:101 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Speichern" -#: bookwyrm/templates/author/edit_author.html:99 -#: bookwyrm/templates/book/book.html:125 bookwyrm/templates/book/book.html:174 +#: bookwyrm/templates/author/edit_author.html:117 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:264 +#: bookwyrm/templates/book/edit_book.html:322 +#: bookwyrm/templates/book/readthrough.html:78 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:78 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:37 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 msgid "Cancel" msgstr "Abbrechen" -#: bookwyrm/templates/book/book.html:31 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "von" -#: bookwyrm/templates/book/book.html:39 bookwyrm/templates/book/book.html:40 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "Buch editieren" -#: bookwyrm/templates/book/book.html:57 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "Cover hinzufügen" -#: bookwyrm/templates/book/book.html:61 +#: bookwyrm/templates/book/book.html:78 #, fuzzy #| msgid "Failed to load" msgid "Failed to load cover" msgstr "Laden fehlgeschlagen" -#: bookwyrm/templates/book/book.html:101 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s Bewertung)" msgstr[1] "(%(review_count)s Bewertungen)" -#: bookwyrm/templates/book/book.html:113 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "Beschreibung hinzufügen" -#: bookwyrm/templates/book/book.html:120 -#: bookwyrm/templates/book/edit_book.html:108 +#: bookwyrm/templates/book/book.html:137 +#: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Beschreibung:" -#: bookwyrm/templates/book/book.html:134 +#: bookwyrm/templates/book/book.html:151 #, fuzzy, python-format #| msgid "%(title)s by " msgid "%(count)s editions" msgstr "%(title)s von" -#: bookwyrm/templates/book/book.html:142 +#: bookwyrm/templates/book/book.html:159 #, fuzzy, python-format #| msgid "Direct Messages with %(username)s" msgid "This edition is on your %(shelf_name)s shelf." msgstr "Direktnachrichten mit %(username)s" -#: bookwyrm/templates/book/book.html:148 +#: bookwyrm/templates/book/book.html:165 #, fuzzy, python-format #| msgid " added %(book_title)s to your list \"%(list_name)s\"" msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "hat %(book_title)s zu deiner Liste \"%(list_name)s\" Hinzugefügt" -#: bookwyrm/templates/book/book.html:159 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "Deine Leseaktivität" -#: bookwyrm/templates/book/book.html:162 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "Lesedaten hinzufügen" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "Erstellen" -#: bookwyrm/templates/book/book.html:181 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "Du hast keine Leseaktivität für dieses Buch." -#: bookwyrm/templates/book/book.html:200 +#: bookwyrm/templates/book/book.html:217 #, fuzzy #| msgid "Review" msgid "Reviews" msgstr "Bewerten" -#: bookwyrm/templates/book/book.html:205 +#: bookwyrm/templates/book/book.html:222 #, fuzzy #| msgid "Your shelves" msgid "Your reviews" msgstr "Deine Regale" -#: bookwyrm/templates/book/book.html:211 +#: bookwyrm/templates/book/book.html:228 #, fuzzy #| msgid "Your Account" msgid "Your comments" msgstr "Dein Account" -#: bookwyrm/templates/book/book.html:217 +#: bookwyrm/templates/book/book.html:234 #, fuzzy #| msgid "Your books" msgid "Your quotes" msgstr "Deine Bücher" -#: bookwyrm/templates/book/book.html:253 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "Themen" -#: bookwyrm/templates/book/book.html:265 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "Orte" -#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:68 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "Listen" -#: bookwyrm/templates/book/book.html:287 +#: bookwyrm/templates/book/book.html:304 #, fuzzy #| msgid "Go to list" msgid "Add to list" msgstr "Zur Liste" -#: bookwyrm/templates/book/book.html:297 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -423,24 +437,24 @@ msgid "ISBN:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:301 msgid "OCLC Number:" msgstr "OCLC Nummer:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:253 +#: bookwyrm/templates/book/edit_book.html:309 msgid "ASIN:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:192 +#: bookwyrm/templates/book/edit_book.html:229 #, fuzzy #| msgid "Add cover" msgid "Upload cover:" msgstr "Cover hinzufügen" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:198 +#: bookwyrm/templates/book/edit_book.html:235 msgid "Load cover from url:" msgstr "Cover von URL laden:" @@ -458,137 +472,143 @@ msgstr "Editionen von %(book_title)s" msgid "Add Book" msgstr "Bücher hinzufügen" -#: bookwyrm/templates/book/edit_book.html:40 +#: bookwyrm/templates/book/edit_book.html:54 msgid "Confirm Book Info" msgstr "Buchinfo bestätigen" -#: bookwyrm/templates/book/edit_book.html:47 +#: bookwyrm/templates/book/edit_book.html:62 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "Existiert \"%(name)s\" bereits als Autor:in?" -#: bookwyrm/templates/book/edit_book.html:52 +#: bookwyrm/templates/book/edit_book.html:71 #, fuzzy, python-format #| msgid "Start \"%(book_title)s\"" msgid "Author of %(book_title)s" msgstr "\"%(book_title)s\" beginnen" -#: bookwyrm/templates/book/edit_book.html:55 +#: bookwyrm/templates/book/edit_book.html:75 msgid "This is a new author" msgstr "Neue:r Autor:in" -#: bookwyrm/templates/book/edit_book.html:61 +#: bookwyrm/templates/book/edit_book.html:82 #, python-format msgid "Creating a new author: %(name)s" msgstr "Neu als Autor:in erstellen: %(name)s" -#: bookwyrm/templates/book/edit_book.html:67 +#: bookwyrm/templates/book/edit_book.html:89 msgid "Is this an edition of an existing work?" msgstr "Ist das eine Edition eines vorhandenen Werkes?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:97 msgid "This is a new work" msgstr "Dies ist ein neues Werk." -#: bookwyrm/templates/book/edit_book.html:77 +#: bookwyrm/templates/book/edit_book.html:104 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "Bestätigen" -#: bookwyrm/templates/book/edit_book.html:79 +#: bookwyrm/templates/book/edit_book.html:106 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "Zurück" -#: bookwyrm/templates/book/edit_book.html:93 +#: bookwyrm/templates/book/edit_book.html:120 msgid "Title:" msgstr "Titel:" -#: bookwyrm/templates/book/edit_book.html:101 +#: bookwyrm/templates/book/edit_book.html:128 msgid "Subtitle:" msgstr "Untertitel:" -#: bookwyrm/templates/book/edit_book.html:114 +#: bookwyrm/templates/book/edit_book.html:144 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:122 +#: bookwyrm/templates/book/edit_book.html:152 msgid "Series number:" msgstr "Seriennummer:" -#: bookwyrm/templates/book/edit_book.html:130 +#: bookwyrm/templates/book/edit_book.html:160 #, fuzzy #| msgid "Pages:" msgid "Languages:" msgstr "Seiten:" -#: bookwyrm/templates/book/edit_book.html:139 +#: bookwyrm/templates/book/edit_book.html:169 #, fuzzy #| msgid "Published" msgid "Publisher:" msgstr "Veröffentlicht" -#: bookwyrm/templates/book/edit_book.html:148 +#: bookwyrm/templates/book/edit_book.html:178 msgid "First published date:" msgstr "Erstveröffentlichungsdatum:" -#: bookwyrm/templates/book/edit_book.html:156 +#: bookwyrm/templates/book/edit_book.html:186 msgid "Published date:" msgstr "Veröffentlichungsdatum:" -#: bookwyrm/templates/book/edit_book.html:165 +#: bookwyrm/templates/book/edit_book.html:195 #, fuzzy #| msgid "Author" msgid "Authors" msgstr "Autor*in" -#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:202 #, fuzzy, python-format -#| msgid "Direct Messages with %(username)s" -msgid "Remove %(name)s" -msgstr "Direktnachrichten mit %(username)s" +#| msgid "Lists: %(username)s" +msgid "Remove %(name)s" +msgstr "Listen: %(username)s" -#: bookwyrm/templates/book/edit_book.html:176 +#: bookwyrm/templates/book/edit_book.html:205 +#, fuzzy, python-format +#| msgid "Lists: %(username)s" +msgid "Author page for %(name)s" +msgstr "Listen: %(username)s" + +#: bookwyrm/templates/book/edit_book.html:212 #, fuzzy #| msgid "Edit Author" msgid "Add Authors:" msgstr "Autor*in editieren" -#: bookwyrm/templates/book/edit_book.html:177 +#: bookwyrm/templates/book/edit_book.html:213 msgid "John Doe, Jane Smith" msgstr "" -#: bookwyrm/templates/book/edit_book.html:183 +#: bookwyrm/templates/book/edit_book.html:220 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "" -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:248 msgid "Physical Properties" msgstr "Physikalische Eigenschaften" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:250 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:258 msgid "Pages:" msgstr "Seiten:" -#: bookwyrm/templates/book/edit_book.html:227 +#: bookwyrm/templates/book/edit_book.html:267 msgid "Book Identifiers" msgstr "Buchidentifikatoren" -#: bookwyrm/templates/book/edit_book.html:228 +#: bookwyrm/templates/book/edit_book.html:269 msgid "ISBN 13:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:233 +#: bookwyrm/templates/book/edit_book.html:277 msgid "ISBN 10:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:238 +#: bookwyrm/templates/book/edit_book.html:285 msgid "Openlibrary ID:" msgstr "" @@ -652,11 +672,40 @@ msgstr "Veröffentlicht von %(publisher)s." msgid "rated it" msgstr "bewertet" +#: bookwyrm/templates/book/readthrough.html:8 +msgid "Progress Updates:" +msgstr "Fortschrittsupdates:" + +#: bookwyrm/templates/book/readthrough.html:14 +msgid "finished" +msgstr "Abgeschlossen" + +#: bookwyrm/templates/book/readthrough.html:25 +msgid "Show all updates" +msgstr "Zeige alle Updates" + +#: bookwyrm/templates/book/readthrough.html:41 +msgid "Delete this progress update" +msgstr "Dieses Fortschrittsupdate löschen" + +#: bookwyrm/templates/book/readthrough.html:52 +msgid "started" +msgstr "Angefangen" + +#: bookwyrm/templates/book/readthrough.html:59 +#: bookwyrm/templates/book/readthrough.html:73 +msgid "Edit read dates" +msgstr "Lesedaten bearbeiten" + +#: bookwyrm/templates/book/readthrough.html:63 +msgid "Delete these read dates" +msgstr "Diese Lesedaten löschen" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:69 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -688,7 +737,7 @@ msgstr "Föderiert" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "" @@ -722,7 +771,16 @@ msgstr "Vorschlagen" msgid "Recently active" msgstr "" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +#, fuzzy +#| msgid "Your Account" +msgid "Locked account" +msgstr "Dein Account" + +#: bookwyrm/templates/directory/user_card.html:40 #, fuzzy #| msgid "followed you" msgid "follower you follow" @@ -730,7 +788,7 @@ msgid_plural "followers you follow" msgstr[0] "folgt dir" msgstr[1] "folgt dir" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 #, fuzzy #| msgid "Your shelves" msgid "book on your shelves" @@ -738,11 +796,11 @@ msgid_plural "books on your shelves" msgstr[0] "Deine Regale" msgstr[1] "Deine Regale" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "" @@ -780,7 +838,7 @@ msgid "Recent Books" msgstr "Aktive Bücher" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "Willkommen" @@ -902,7 +960,7 @@ msgid "Direct Messages with %(username)s" msgstr "Direktnachrichten mit %(username)s" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "Direktnachrichten" @@ -946,67 +1004,53 @@ msgstr "Föderiert" msgid "load 0 unread status(es)" msgstr "" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "Hier sind noch keine Aktivitäten! Folge anderen, um loszulegen" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "" - -#: bookwyrm/templates/feed/feed_layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:10 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "Deine Bücher" -#: bookwyrm/templates/feed/feed_layout.html:12 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "Hier sind noch keine Bücher! Versuche nach Büchern zu suchen um loszulegen" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 #, fuzzy #| msgid "Read" msgid "To Read" msgstr "Auf der Leseliste" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 #, fuzzy #| msgid "Start reading" msgid "Currently Reading" msgstr "Gerade lesend" -#: bookwyrm/templates/feed/feed_layout.html:25 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13 +#: bookwyrm/templates/feed/layout.html:27 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "Gelesen" -#: bookwyrm/templates/feed/feed_layout.html:87 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "%(year)s Leseziel" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "" -msgstr[1] "" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "" -msgstr[1] "" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "" #: bookwyrm/templates/get_started/book_preview.html:6 #, fuzzy, python-format @@ -1040,7 +1084,7 @@ msgstr "" #: bookwyrm/templates/get_started/books.html:17 #: 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/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -1069,40 +1113,40 @@ msgstr "Keine Bücher gefunden" msgid "Save & continue" msgstr "" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, fuzzy, python-format #| msgid "About %(site_name)s" msgid "Welcome to %(site_name)s!" msgstr "Über %(site_name)s" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "" -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 #, fuzzy #| msgid "User Profile" msgid "Create your profile" msgstr "Benutzerprofil" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 #, fuzzy #| msgid "Add Books" msgid "Add books" msgstr "Bücher hinzufügen" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 #, fuzzy #| msgid "Friendly" msgid "Find friends" msgstr "Freundlich" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 #, fuzzy #| msgid "Finished" msgid "Finish" @@ -1133,7 +1177,7 @@ msgid "Manually approve followers:" msgstr "Folgende manuell bestätigen" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "" @@ -1218,70 +1262,87 @@ msgstr "Aktuelle Importe" msgid "No recent imports" msgstr "Keine aktuellen Importe" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "Importstatus" -#: bookwyrm/templates/import_status.html:12 +#: bookwyrm/templates/import_status.html:11 +#, fuzzy +#| msgid "Back to reports" +msgid "Back to imports" +msgstr "Zurück zu den Meldungen" + +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "Import gestartet:" -#: bookwyrm/templates/import_status.html:16 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "Import abgeschlossen:" -#: bookwyrm/templates/import_status.html:19 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "AUFGABE GESCHEITERT" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "Import läuft noch." -#: bookwyrm/templates/import_status.html:27 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "(Aktualisiere für ein Update!)" -#: bookwyrm/templates/import_status.html:34 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "Laden fehlgeschlagen" -#: bookwyrm/templates/import_status.html:43 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "Zum Ende der Liste springen, um die %(failed_count)s Einträge, deren Import fehlschlug, auszuwählen." -#: bookwyrm/templates/import_status.html:78 +#: bookwyrm/templates/import_status.html:62 +#, python-format +msgid "Line %(index)s: %(title)s by %(author)s" +msgstr "" + +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "Alle auswählen" -#: bookwyrm/templates/import_status.html:81 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "Punkte erneut versuchen" -#: bookwyrm/templates/import_status.html:107 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "Erfolgreich importiert" -#: bookwyrm/templates/import_status.html:111 +#: bookwyrm/templates/import_status.html:114 +#, fuzzy +#| msgid "Import still in progress." +msgid "Import Progress" +msgstr "Import läuft noch." + +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "Buch" -#: bookwyrm/templates/import_status.html:114 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: 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/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "Autor*in" -#: bookwyrm/templates/import_status.html:140 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "Importiert" @@ -1311,29 +1372,29 @@ msgstr "Suchergebnisse für \"%(query)s\"" msgid "Matching Books" msgstr "Passende Bücher" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "Suche nach Buch oder Benutzer*in" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "Navigationshauptmenü" -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "" -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:94 #, fuzzy #| msgid "Your books" msgid "Your Books" msgstr "Deine Bücher" -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "Einstellungen" -#: bookwyrm/templates/layout.html:106 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1341,65 +1402,65 @@ msgstr "Einstellungen" msgid "Invites" msgstr "Einladungen" -#: bookwyrm/templates/layout.html:113 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "" -#: bookwyrm/templates/layout.html:120 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "Abmelden" -#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "Benachrichtigungen" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "Passwort" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "Passwort vergessen?" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "Anmelden" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:213 #, fuzzy #| msgid "About this server" msgid "About this instance" msgstr "Über diesen Server" -#: bookwyrm/templates/layout.html:210 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "Admin kontaktieren" -#: bookwyrm/templates/layout.html:214 +#: bookwyrm/templates/layout.html:221 #, fuzzy #| msgid "List curation:" msgid "Documentation" msgstr "Listenkuratierung:" -#: bookwyrm/templates/layout.html:221 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "%(site_name)s auf %(support_title)s unterstützen" -#: bookwyrm/templates/layout.html:225 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm ist open source Software. Du kannst dich auf GitHub beteiligen oder etwas melden." @@ -1809,6 +1870,7 @@ msgstr "Du bist auf dem neusten Stand!" #: bookwyrm/templates/password_reset.html:23 #: bookwyrm/templates/preferences/change_password.html:18 +#: bookwyrm/templates/preferences/delete_user.html:20 msgid "Confirm password:" msgstr "Passwort bestätigen:" @@ -1822,7 +1884,7 @@ msgstr "Passwort zurücksetzen" #: bookwyrm/templates/preferences/blocks.html:4 #: bookwyrm/templates/preferences/blocks.html:7 -#: bookwyrm/templates/preferences/preferences_layout.html:26 +#: bookwyrm/templates/preferences/layout.html:30 msgid "Blocked Users" msgstr "Blockierte Nutzer*innen" @@ -1833,7 +1895,7 @@ msgstr "Momentan keine Nutzer*innen blockiert." #: bookwyrm/templates/preferences/change_password.html:4 #: bookwyrm/templates/preferences/change_password.html:7 #: bookwyrm/templates/preferences/change_password.html:21 -#: bookwyrm/templates/preferences/preferences_layout.html:19 +#: bookwyrm/templates/preferences/layout.html:19 msgid "Change Password" msgstr "Passwort ändern" @@ -1841,6 +1903,23 @@ msgstr "Passwort ändern" msgid "New password:" msgstr "Neues Passwort:" +#: bookwyrm/templates/preferences/delete_user.html:4 +#: bookwyrm/templates/preferences/delete_user.html:7 +#: bookwyrm/templates/preferences/delete_user.html:26 +#: bookwyrm/templates/preferences/layout.html:23 +#, fuzzy +#| msgid "Create an Account" +msgid "Delete Account" +msgstr "Erstelle einen Account" + +#: bookwyrm/templates/preferences/delete_user.html:12 +msgid "Permanently delete account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:14 +msgid "Deleting your account cannot be undone. The username will not be available to register in the future." +msgstr "" + #: bookwyrm/templates/preferences/edit_user.html:4 #: bookwyrm/templates/preferences/edit_user.html:7 msgid "Edit Profile" @@ -1850,44 +1929,68 @@ msgstr "Profil bearbeiten:" msgid "Show set reading goal prompt in feed:" msgstr "Angegebenes Leseziel im Feed anzeigen." -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +#, fuzzy +#| msgid "Goal privacy:" +msgid "Default post privacy:" +msgstr "Sichtbarkeit des Ziels" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "" -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "" -#: bookwyrm/templates/preferences/preferences_layout.html:11 +#: bookwyrm/templates/preferences/layout.html:11 msgid "Account" msgstr "" -#: bookwyrm/templates/preferences/preferences_layout.html:15 +#: bookwyrm/templates/preferences/layout.html:15 msgid "Profile" msgstr "Profil" -#: bookwyrm/templates/preferences/preferences_layout.html:22 +#: bookwyrm/templates/preferences/layout.html:26 msgid "Relationships" msgstr "Beziehungen" +#: bookwyrm/templates/reading_progress/finish.html:5 +#, fuzzy, python-format +#| msgid "Finish \"%(book_title)s\"" +msgid "Finish \"%(book_title)s\"" +msgstr "\"%(book_title)s\" abschließen" + +#: bookwyrm/templates/reading_progress/start.html:5 +#, fuzzy, python-format +#| msgid "Editions of %(book_title)s" +msgid "Start \"%(book_title)s\"" +msgstr "Editionen von %(book_title)s" + +#: bookwyrm/templates/reading_progress/want.html:5 +#, fuzzy, python-format +#| msgid "Want to Read \"%(book_title)s\"" +msgid "Want to Read \"%(book_title)s\"" +msgstr "\"%(book_title)s\" auf Leseliste setzen" + #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "bewertete" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "kommentierte" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "zitierte" @@ -1919,7 +2022,7 @@ msgstr "Suche" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:74 +#: bookwyrm/templates/user/layout.html:81 #, fuzzy #| msgid "Book" msgid "Books" @@ -2169,7 +2272,7 @@ msgid "Details" msgstr "" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:56 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "Aktivität" @@ -2218,7 +2321,7 @@ msgid "Edit" msgstr "Buch editieren" #: bookwyrm/templates/settings/federated_server.html:105 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:8 #, fuzzy #| msgid "Notifications" msgid "Actions" @@ -2448,17 +2551,19 @@ msgstr "" msgid "Additional info:" msgstr "" -#: bookwyrm/templates/settings/site.html:83 -msgid "Allow registration:" +#: bookwyrm/templates/settings/site.html:85 +#, fuzzy +#| msgid "Allow registration:" +msgid "Allow registration" msgstr "Registrierungen erlauben" -#: bookwyrm/templates/settings/site.html:87 +#: bookwyrm/templates/settings/site.html:91 #, fuzzy #| msgid "Follow Requests" -msgid "Allow invite requests:" +msgid "Allow invite requests" msgstr "Folgeanfragen" -#: bookwyrm/templates/settings/site.html:91 +#: bookwyrm/templates/settings/site.html:95 msgid "Registration closed text:" msgstr "Registrierungen geschlossen text" @@ -2468,7 +2573,7 @@ msgstr "Registrierungen geschlossen text" msgid "Posted by %(username)s" msgstr "Direktnachrichten mit %(username)s" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 #, fuzzy #| msgid "Add cover" msgid "No cover" @@ -2570,7 +2675,7 @@ msgstr "Spoileralarm aktivieren" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "Privat" @@ -2696,7 +2801,7 @@ msgstr "Sichtbarkeit des Ziels" #: bookwyrm/templates/snippets/goal_form.html:26 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:29 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 msgid "Post to feed" msgstr "Posten" @@ -2742,13 +2847,13 @@ msgstr "Weiter" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "Öffentlich" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "Ungelistet" @@ -2760,7 +2865,7 @@ msgstr "Nur für Folgende" msgid "Post privacy" msgstr "" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2774,38 +2879,9 @@ msgstr "Raten" msgid "Rate" msgstr "" -#: bookwyrm/templates/snippets/readthrough.html:8 -msgid "Progress Updates:" -msgstr "Fortschrittsupdates:" - -#: bookwyrm/templates/snippets/readthrough.html:14 -msgid "finished" -msgstr "Abgeschlossen" - -#: bookwyrm/templates/snippets/readthrough.html:25 -msgid "Show all updates" -msgstr "Zeige alle Updates" - -#: bookwyrm/templates/snippets/readthrough.html:41 -msgid "Delete this progress update" -msgstr "Dieses Fortschrittsupdate löschen" - -#: bookwyrm/templates/snippets/readthrough.html:52 -msgid "started" -msgstr "Angefangen" - -#: bookwyrm/templates/snippets/readthrough.html:59 -#: bookwyrm/templates/snippets/readthrough.html:73 -msgid "Edit read dates" -msgstr "Lesedaten bearbeiten" - -#: bookwyrm/templates/snippets/readthrough.html:63 -msgid "Delete these read dates" -msgstr "Diese Lesedaten löschen" - #: bookwyrm/templates/snippets/readthrough_form.html:7 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:17 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Zu lesen angefangen" @@ -2844,7 +2920,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "\"%(book_title)s\" abschließen" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:36 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 #, fuzzy #| msgid "Progress" msgid "Update progress" @@ -2854,20 +2930,20 @@ msgstr "Fortschritt" msgid "More shelves" msgstr "Mehr Regale" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:10 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 msgid "Start reading" msgstr "Zu lesen beginnen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:15 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 msgid "Finish reading" msgstr "Lesen abschließen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:18 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 msgid "Want to read" msgstr "Auf Leseliste setzen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 #, fuzzy, python-format #| msgid "Lists: %(username)s" msgid "Remove from %(name)s" @@ -2883,17 +2959,17 @@ msgstr "\"%(book_title)s\" beginnen" msgid "Want to Read \"%(book_title)s\"" msgstr "\"%(book_title)s\" auf Leseliste setzen" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "Mehr anzeigen" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "Weniger anzeigen" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "Bild in neuem Fenster öffnen" @@ -2916,7 +2992,7 @@ msgstr "Status favorisieren" msgid "boosted" msgstr "teilt" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, fuzzy, python-format #| msgid "replied to your status" msgid "replied to %(username)s's status" @@ -2935,10 +3011,31 @@ msgstr "Diese Lesedaten löschen" #: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:12 msgid "Send direct message" msgstr "Direktnachricht senden" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "" +msgstr[1] "" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "" +msgstr[1] "" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +#, fuzzy +#| msgid "followed you" +msgid "Follows you" +msgstr "folgt dir" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "Zu dieser Edition wechseln" @@ -2955,15 +3052,15 @@ msgstr "Zu lesen angefangen" msgid "Sorted descending" msgstr "Zu lesen angefangen" -#: bookwyrm/templates/user/layout.html:13 bookwyrm/templates/user/user.html:10 +#: bookwyrm/templates/user/layout.html:18 bookwyrm/templates/user/user.html:10 msgid "User Profile" msgstr "Benutzerprofil" -#: bookwyrm/templates/user/layout.html:37 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "Folgeanfragen" -#: bookwyrm/templates/user/layout.html:62 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "Leseziel" @@ -3073,24 +3170,24 @@ msgstr "" msgid "No activities yet!" msgstr "Noch keine Aktivitäten!" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "Beigetreten %(date)s" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "%(counter)s Folgende*r" msgstr[1] "%(counter)s Folgende" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "Folgt %(counter)s" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, fuzzy, python-format #| msgid "followed you" msgid "%(mutuals_display)s follower you follow" @@ -3098,6 +3195,12 @@ msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "folgt dir" msgstr[1] "folgt dir" +#: bookwyrm/templates/user/user_preview.html:38 +#, fuzzy +#| msgid "followed you" +msgid "No followers you follow" +msgstr "folgt dir" + #: bookwyrm/templates/user_admin/user.html:9 #, fuzzy #| msgid "Back to reports" @@ -3168,22 +3271,31 @@ msgstr "Instanzeinstellungen" msgid "View instance" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:5 +msgid "Permanently deleted" +msgstr "" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:17 msgid "Suspend user" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:19 msgid "Un-suspend user" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:28 msgid "Access level:" msgstr "" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 msgid "File exceeds maximum size: 10MB" msgstr "" +#: bookwyrm/templatetags/utilities.py:30 +#, python-format +msgid "%(title)s: %(subtitle)s" +msgstr "" + #: bookwyrm/views/import_data.py:67 #, fuzzy #| msgid "Email address:" @@ -3201,6 +3313,11 @@ msgstr "Dieser Benutzename ist bereits vergeben." msgid "A password reset link sent to %s" msgstr "" +#, fuzzy +#~| msgid "Direct Messages with %(username)s" +#~ msgid "Remove %(name)s" +#~ msgstr "Direktnachrichten mit %(username)s" + #, fuzzy #~| msgid "Lists: %(username)s" #~ msgid "Reports: %(server_name)s" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index 8c36a2cb3..ce06013f2 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-06 20:52+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,99 +18,103 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:224 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "" -#: bookwyrm/forms.py:238 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "" -#: bookwyrm/forms.py:239 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "" -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "" -#: bookwyrm/forms.py:299 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:300 +#: bookwyrm/forms.py:308 msgid "Book Title" msgstr "" -#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: 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:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:315 msgid "Ascending" msgstr "" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:316 msgid "Descending" msgstr "" -#: bookwyrm/models/fields.py:25 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "" -#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "" -#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "" -#: bookwyrm/models/fields.py:171 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "" -#: bookwyrm/settings.py:156 +#: bookwyrm/settings.py:166 msgid "English" msgstr "" -#: bookwyrm/settings.py:157 +#: bookwyrm/settings.py:167 msgid "German" msgstr "" -#: bookwyrm/settings.py:158 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "" -#: bookwyrm/settings.py:159 +#: bookwyrm/settings.py:169 msgid "French" msgstr "" -#: bookwyrm/settings.py:160 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "" +#: bookwyrm/settings.py:171 +msgid "Traditional Chinese" +msgstr "" + #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" msgstr "" @@ -136,34 +140,42 @@ msgstr "" msgid "Edit Author" msgstr "" -#: bookwyrm/templates/author/author.html:32 -#: bookwyrm/templates/author/edit_author.html:38 +#: bookwyrm/templates/author/author.html:34 +#: bookwyrm/templates/author/edit_author.html:41 msgid "Aliases:" msgstr "" -#: bookwyrm/templates/author/author.html:38 +#: bookwyrm/templates/author/author.html:45 msgid "Born:" msgstr "" -#: bookwyrm/templates/author/author.html:44 +#: bookwyrm/templates/author/author.html:52 msgid "Died:" msgstr "" -#: bookwyrm/templates/author/author.html:51 +#: bookwyrm/templates/author/author.html:61 msgid "Wikipedia" msgstr "" -#: bookwyrm/templates/author/author.html:55 -#: bookwyrm/templates/book/book.html:78 +#: bookwyrm/templates/author/author.html:69 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "" -#: bookwyrm/templates/author/author.html:60 -#: bookwyrm/templates/book/book.html:81 +#: bookwyrm/templates/author/author.html:77 +#: bookwyrm/templates/book/book.html:98 msgid "View on Inventaire" msgstr "" -#: bookwyrm/templates/author/author.html:74 +#: bookwyrm/templates/author/author.html:85 +msgid "View on LibraryThing" +msgstr "" + +#: bookwyrm/templates/author/author.html:93 +msgid "View on Goodreads" +msgstr "" + +#: bookwyrm/templates/author/author.html:108 #, python-format msgid "Books by %(name)s" msgstr "" @@ -173,213 +185,213 @@ msgid "Edit Author:" msgstr "" #: bookwyrm/templates/author/edit_author.html:13 -#: bookwyrm/templates/book/edit_book.html:18 +#: bookwyrm/templates/book/edit_book.html:19 msgid "Added:" msgstr "" #: bookwyrm/templates/author/edit_author.html:14 -#: bookwyrm/templates/book/edit_book.html:19 +#: bookwyrm/templates/book/edit_book.html:24 msgid "Updated:" msgstr "" #: bookwyrm/templates/author/edit_author.html:15 -#: bookwyrm/templates/book/edit_book.html:20 +#: bookwyrm/templates/book/edit_book.html:30 msgid "Last edited by:" msgstr "" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:90 +#: bookwyrm/templates/book/edit_book.html:117 msgid "Metadata" msgstr "" -#: bookwyrm/templates/author/edit_author.html:32 +#: bookwyrm/templates/author/edit_author.html:33 #: bookwyrm/templates/lists/form.html:8 #: bookwyrm/templates/user/shelf/create_shelf_form.html:13 #: bookwyrm/templates/user/shelf/edit_shelf_form.html:14 msgid "Name:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:40 -#: bookwyrm/templates/book/edit_book.html:132 -#: bookwyrm/templates/book/edit_book.html:141 -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/author/edit_author.html:43 +#: bookwyrm/templates/book/edit_book.html:162 +#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:214 msgid "Separate multiple values with commas." msgstr "" -#: bookwyrm/templates/author/edit_author.html:46 +#: bookwyrm/templates/author/edit_author.html:50 msgid "Bio:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:51 +#: bookwyrm/templates/author/edit_author.html:57 msgid "Wikipedia link:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:57 +#: bookwyrm/templates/author/edit_author.html:63 msgid "Birth date:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:65 +#: bookwyrm/templates/author/edit_author.html:71 msgid "Death date:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:73 +#: bookwyrm/templates/author/edit_author.html:79 msgid "Author Identifiers" msgstr "" -#: bookwyrm/templates/author/edit_author.html:74 +#: bookwyrm/templates/author/edit_author.html:81 msgid "Openlibrary key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:79 -#: bookwyrm/templates/book/edit_book.html:243 +#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/book/edit_book.html:293 msgid "Inventaire ID:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:84 +#: bookwyrm/templates/author/edit_author.html:97 msgid "Librarything key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/author/edit_author.html:105 msgid "Goodreads key:" msgstr "" -#: bookwyrm/templates/author/edit_author.html:98 -#: bookwyrm/templates/book/book.html:124 -#: bookwyrm/templates/book/edit_book.html:263 +#: bookwyrm/templates/author/edit_author.html:116 +#: bookwyrm/templates/book/book.html:141 +#: bookwyrm/templates/book/edit_book.html:321 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: 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 -#: bookwyrm/templates/snippets/readthrough.html:77 +#: bookwyrm/templates/settings/site.html:101 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "" -#: bookwyrm/templates/author/edit_author.html:99 -#: bookwyrm/templates/book/book.html:125 bookwyrm/templates/book/book.html:174 +#: bookwyrm/templates/author/edit_author.html:117 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:264 +#: bookwyrm/templates/book/edit_book.html:322 +#: bookwyrm/templates/book/readthrough.html:78 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:78 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:37 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 msgid "Cancel" msgstr "" -#: bookwyrm/templates/book/book.html:31 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "" -#: bookwyrm/templates/book/book.html:39 bookwyrm/templates/book/book.html:40 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "" -#: bookwyrm/templates/book/book.html:57 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "" -#: bookwyrm/templates/book/book.html:61 +#: bookwyrm/templates/book/book.html:78 msgid "Failed to load cover" msgstr "" -#: bookwyrm/templates/book/book.html:101 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/book/book.html:113 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "" -#: bookwyrm/templates/book/book.html:120 -#: bookwyrm/templates/book/edit_book.html:108 +#: bookwyrm/templates/book/book.html:137 +#: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "" -#: bookwyrm/templates/book/book.html:134 +#: bookwyrm/templates/book/book.html:151 #, python-format msgid "%(count)s editions" msgstr "" -#: bookwyrm/templates/book/book.html:142 +#: bookwyrm/templates/book/book.html:159 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "" -#: bookwyrm/templates/book/book.html:148 +#: bookwyrm/templates/book/book.html:165 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "" -#: bookwyrm/templates/book/book.html:159 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "" -#: bookwyrm/templates/book/book.html:162 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "" -#: bookwyrm/templates/book/book.html:181 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "" -#: bookwyrm/templates/book/book.html:200 +#: bookwyrm/templates/book/book.html:217 msgid "Reviews" msgstr "" -#: bookwyrm/templates/book/book.html:205 +#: bookwyrm/templates/book/book.html:222 msgid "Your reviews" msgstr "" -#: bookwyrm/templates/book/book.html:211 +#: bookwyrm/templates/book/book.html:228 msgid "Your comments" msgstr "" -#: bookwyrm/templates/book/book.html:217 +#: bookwyrm/templates/book/book.html:234 msgid "Your quotes" msgstr "" -#: bookwyrm/templates/book/book.html:253 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "" -#: bookwyrm/templates/book/book.html:265 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "" -#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:68 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "" -#: bookwyrm/templates/book/book.html:287 +#: bookwyrm/templates/book/book.html:304 msgid "Add to list" msgstr "" -#: bookwyrm/templates/book/book.html:297 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -390,22 +402,22 @@ msgid "ISBN:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:301 msgid "OCLC Number:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:253 +#: bookwyrm/templates/book/edit_book.html:309 msgid "ASIN:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:192 +#: bookwyrm/templates/book/edit_book.html:229 msgid "Upload cover:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:198 +#: bookwyrm/templates/book/edit_book.html:235 msgid "Load cover from url:" msgstr "" @@ -420,127 +432,132 @@ msgstr "" msgid "Add Book" msgstr "" -#: bookwyrm/templates/book/edit_book.html:40 +#: bookwyrm/templates/book/edit_book.html:54 msgid "Confirm Book Info" msgstr "" -#: bookwyrm/templates/book/edit_book.html:47 +#: bookwyrm/templates/book/edit_book.html:62 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "" -#: bookwyrm/templates/book/edit_book.html:52 +#: bookwyrm/templates/book/edit_book.html:71 #, python-format msgid "Author of %(book_title)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:55 +#: bookwyrm/templates/book/edit_book.html:75 msgid "This is a new author" msgstr "" -#: bookwyrm/templates/book/edit_book.html:61 +#: bookwyrm/templates/book/edit_book.html:82 #, python-format msgid "Creating a new author: %(name)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:67 +#: bookwyrm/templates/book/edit_book.html:89 msgid "Is this an edition of an existing work?" msgstr "" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:97 msgid "This is a new work" msgstr "" -#: bookwyrm/templates/book/edit_book.html:77 +#: bookwyrm/templates/book/edit_book.html:104 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "" -#: bookwyrm/templates/book/edit_book.html:79 +#: bookwyrm/templates/book/edit_book.html:106 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "" -#: bookwyrm/templates/book/edit_book.html:93 +#: bookwyrm/templates/book/edit_book.html:120 msgid "Title:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:101 +#: bookwyrm/templates/book/edit_book.html:128 msgid "Subtitle:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:114 +#: bookwyrm/templates/book/edit_book.html:144 msgid "Series:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:122 +#: bookwyrm/templates/book/edit_book.html:152 msgid "Series number:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:130 +#: bookwyrm/templates/book/edit_book.html:160 msgid "Languages:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:139 +#: bookwyrm/templates/book/edit_book.html:169 msgid "Publisher:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:148 +#: bookwyrm/templates/book/edit_book.html:178 msgid "First published date:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:156 +#: bookwyrm/templates/book/edit_book.html:186 msgid "Published date:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:165 +#: bookwyrm/templates/book/edit_book.html:195 msgid "Authors" msgstr "" -#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:202 #, python-format -msgid "Remove %(name)s" +msgid "Remove %(name)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:176 +#: bookwyrm/templates/book/edit_book.html:205 +#, python-format +msgid "Author page for %(name)s" +msgstr "" + +#: bookwyrm/templates/book/edit_book.html:212 msgid "Add Authors:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:177 +#: bookwyrm/templates/book/edit_book.html:213 msgid "John Doe, Jane Smith" msgstr "" -#: bookwyrm/templates/book/edit_book.html:183 +#: bookwyrm/templates/book/edit_book.html:220 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "" -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:248 msgid "Physical Properties" msgstr "" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:250 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:258 msgid "Pages:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:227 +#: bookwyrm/templates/book/edit_book.html:267 msgid "Book Identifiers" msgstr "" -#: bookwyrm/templates/book/edit_book.html:228 +#: bookwyrm/templates/book/edit_book.html:269 msgid "ISBN 13:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:233 +#: bookwyrm/templates/book/edit_book.html:277 msgid "ISBN 10:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:238 +#: bookwyrm/templates/book/edit_book.html:285 msgid "Openlibrary ID:" msgstr "" @@ -602,11 +619,40 @@ msgstr "" msgid "rated it" msgstr "" +#: bookwyrm/templates/book/readthrough.html:8 +msgid "Progress Updates:" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:14 +msgid "finished" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:25 +msgid "Show all updates" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:41 +msgid "Delete this progress update" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:52 +msgid "started" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:59 +#: bookwyrm/templates/book/readthrough.html:73 +msgid "Edit read dates" +msgstr "" + +#: bookwyrm/templates/book/readthrough.html:63 +msgid "Delete these read dates" +msgstr "" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:69 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -630,7 +676,7 @@ msgstr "" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "" @@ -661,23 +707,30 @@ msgstr "" msgid "Recently active" msgstr "" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +msgid "Locked account" +msgstr "" + +#: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" msgid_plural "followers you follow" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 msgid "book on your shelves" msgid_plural "books on your shelves" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "" @@ -713,7 +766,7 @@ msgid "Recent Books" msgstr "" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "" @@ -831,7 +884,7 @@ msgid "Direct Messages with %(username)s" msgstr "" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "" @@ -873,63 +926,49 @@ msgstr "" msgid "load 0 unread status(es)" msgstr "" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "" - -#: bookwyrm/templates/feed/feed_layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:10 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:12 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "To Read" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Currently Reading" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:25 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13 +#: bookwyrm/templates/feed/layout.html:27 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "" -#: bookwyrm/templates/feed/feed_layout.html:87 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "" -msgstr[1] "" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "" -msgstr[1] "" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "" #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format @@ -960,7 +999,7 @@ msgstr "" #: bookwyrm/templates/get_started/books.html:17 #: 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/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -986,33 +1025,33 @@ msgstr "" msgid "Save & continue" msgstr "" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, python-format msgid "Welcome to %(site_name)s!" msgstr "" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "" -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 msgid "Create your profile" msgstr "" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 msgid "Add books" msgstr "" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 msgid "Find friends" msgstr "" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 msgid "Finish" msgstr "" @@ -1041,7 +1080,7 @@ msgid "Manually approve followers:" msgstr "" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "" @@ -1122,70 +1161,83 @@ msgstr "" msgid "No recent imports" msgstr "" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "" -#: bookwyrm/templates/import_status.html:12 +#: bookwyrm/templates/import_status.html:11 +msgid "Back to imports" +msgstr "" + +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "" -#: bookwyrm/templates/import_status.html:16 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "" -#: bookwyrm/templates/import_status.html:19 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "" -#: bookwyrm/templates/import_status.html:27 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "" -#: bookwyrm/templates/import_status.html:34 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "" -#: bookwyrm/templates/import_status.html:43 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "" -#: bookwyrm/templates/import_status.html:78 +#: bookwyrm/templates/import_status.html:62 +#, python-format +msgid "Line %(index)s: %(title)s by %(author)s" +msgstr "" + +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "" -#: bookwyrm/templates/import_status.html:81 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "" -#: bookwyrm/templates/import_status.html:107 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "" -#: bookwyrm/templates/import_status.html:111 +#: bookwyrm/templates/import_status.html:114 +msgid "Import Progress" +msgstr "" + +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "" -#: bookwyrm/templates/import_status.html:114 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: 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/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "" -#: bookwyrm/templates/import_status.html:140 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "" @@ -1215,27 +1267,27 @@ msgstr "" msgid "Matching Books" msgstr "" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "" -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "" -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:94 msgid "Your Books" msgstr "" -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "" -#: bookwyrm/templates/layout.html:106 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1243,61 +1295,61 @@ msgstr "" msgid "Invites" msgstr "" -#: bookwyrm/templates/layout.html:113 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "" -#: bookwyrm/templates/layout.html:120 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "" -#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:213 msgid "About this instance" msgstr "" -#: bookwyrm/templates/layout.html:210 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "" -#: bookwyrm/templates/layout.html:214 +#: bookwyrm/templates/layout.html:221 msgid "Documentation" msgstr "" -#: bookwyrm/templates/layout.html:221 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "" -#: bookwyrm/templates/layout.html:225 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "" @@ -1675,6 +1727,7 @@ msgstr "" #: bookwyrm/templates/password_reset.html:23 #: bookwyrm/templates/preferences/change_password.html:18 +#: bookwyrm/templates/preferences/delete_user.html:20 msgid "Confirm password:" msgstr "" @@ -1688,7 +1741,7 @@ msgstr "" #: bookwyrm/templates/preferences/blocks.html:4 #: bookwyrm/templates/preferences/blocks.html:7 -#: bookwyrm/templates/preferences/preferences_layout.html:26 +#: bookwyrm/templates/preferences/layout.html:30 msgid "Blocked Users" msgstr "" @@ -1699,7 +1752,7 @@ msgstr "" #: bookwyrm/templates/preferences/change_password.html:4 #: bookwyrm/templates/preferences/change_password.html:7 #: bookwyrm/templates/preferences/change_password.html:21 -#: bookwyrm/templates/preferences/preferences_layout.html:19 +#: bookwyrm/templates/preferences/layout.html:19 msgid "Change Password" msgstr "" @@ -1707,6 +1760,21 @@ msgstr "" msgid "New password:" msgstr "" +#: bookwyrm/templates/preferences/delete_user.html:4 +#: bookwyrm/templates/preferences/delete_user.html:7 +#: bookwyrm/templates/preferences/delete_user.html:26 +#: bookwyrm/templates/preferences/layout.html:23 +msgid "Delete Account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:12 +msgid "Permanently delete account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:14 +msgid "Deleting your account cannot be undone. The username will not be available to register in the future." +msgstr "" + #: bookwyrm/templates/preferences/edit_user.html:4 #: bookwyrm/templates/preferences/edit_user.html:7 msgid "Edit Profile" @@ -1716,44 +1784,63 @@ msgstr "" msgid "Show set reading goal prompt in feed:" msgstr "" -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +msgid "Default post privacy:" +msgstr "" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "" -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "" -#: bookwyrm/templates/preferences/preferences_layout.html:11 +#: bookwyrm/templates/preferences/layout.html:11 msgid "Account" msgstr "" -#: bookwyrm/templates/preferences/preferences_layout.html:15 +#: bookwyrm/templates/preferences/layout.html:15 msgid "Profile" msgstr "" -#: bookwyrm/templates/preferences/preferences_layout.html:22 +#: bookwyrm/templates/preferences/layout.html:26 msgid "Relationships" msgstr "" +#: bookwyrm/templates/reading_progress/finish.html:5 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/reading_progress/start.html:5 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/reading_progress/want.html:5 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "" @@ -1779,7 +1866,7 @@ msgstr "" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:74 +#: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "" @@ -1984,7 +2071,7 @@ msgid "Details" msgstr "" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:56 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "" @@ -2023,7 +2110,7 @@ msgid "Edit" msgstr "" #: bookwyrm/templates/settings/federated_server.html:105 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:8 msgid "Actions" msgstr "" @@ -2229,15 +2316,15 @@ msgstr "" msgid "Additional info:" msgstr "" -#: bookwyrm/templates/settings/site.html:83 -msgid "Allow registration:" -msgstr "" - -#: bookwyrm/templates/settings/site.html:87 -msgid "Allow invite requests:" +#: bookwyrm/templates/settings/site.html:85 +msgid "Allow registration" msgstr "" #: bookwyrm/templates/settings/site.html:91 +msgid "Allow invite requests" +msgstr "" + +#: bookwyrm/templates/settings/site.html:95 msgid "Registration closed text:" msgstr "" @@ -2246,7 +2333,7 @@ msgstr "" msgid "Posted by %(username)s" msgstr "" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "" @@ -2334,7 +2421,7 @@ msgstr "" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "" @@ -2451,7 +2538,7 @@ msgstr "" #: bookwyrm/templates/snippets/goal_form.html:26 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:29 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 msgid "Post to feed" msgstr "" @@ -2495,13 +2582,13 @@ msgstr "" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "" @@ -2513,7 +2600,7 @@ msgstr "" msgid "Post privacy" msgstr "" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2527,38 +2614,9 @@ msgstr "" msgid "Rate" msgstr "" -#: bookwyrm/templates/snippets/readthrough.html:8 -msgid "Progress Updates:" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:14 -msgid "finished" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:25 -msgid "Show all updates" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:41 -msgid "Delete this progress update" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:52 -msgid "started" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:59 -#: bookwyrm/templates/snippets/readthrough.html:73 -msgid "Edit read dates" -msgstr "" - -#: bookwyrm/templates/snippets/readthrough.html:63 -msgid "Delete these read dates" -msgstr "" - #: bookwyrm/templates/snippets/readthrough_form.html:7 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:17 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "" @@ -2593,7 +2651,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:36 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 msgid "Update progress" msgstr "" @@ -2601,20 +2659,20 @@ msgstr "" msgid "More shelves" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:10 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 msgid "Start reading" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:15 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 msgid "Finish reading" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:18 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 msgid "Want to read" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 #, python-format msgid "Remove from %(name)s" msgstr "" @@ -2629,17 +2687,17 @@ msgstr "" msgid "Want to Read \"%(book_title)s\"" msgstr "" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "" @@ -2662,7 +2720,7 @@ msgstr "" msgid "boosted" msgstr "" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, python-format msgid "replied to %(username)s's status" msgstr "" @@ -2678,10 +2736,29 @@ msgstr "" #: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:12 msgid "Send direct message" msgstr "" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "" +msgstr[1] "" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "" +msgstr[1] "" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +msgid "Follows you" +msgstr "" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "" @@ -2694,15 +2771,15 @@ msgstr "" msgid "Sorted descending" msgstr "" -#: bookwyrm/templates/user/layout.html:13 bookwyrm/templates/user/user.html:10 +#: bookwyrm/templates/user/layout.html:18 bookwyrm/templates/user/user.html:10 msgid "User Profile" msgstr "" -#: bookwyrm/templates/user/layout.html:37 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "" -#: bookwyrm/templates/user/layout.html:62 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "" @@ -2808,30 +2885,34 @@ msgstr "" msgid "No activities yet!" msgstr "" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "" msgstr[1] "" +#: bookwyrm/templates/user/user_preview.html:38 +msgid "No followers you follow" +msgstr "" + #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" msgstr "" @@ -2887,22 +2968,31 @@ msgstr "" msgid "View instance" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:5 +msgid "Permanently deleted" +msgstr "" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:17 msgid "Suspend user" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:19 msgid "Un-suspend user" msgstr "" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:28 msgid "Access level:" msgstr "" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 msgid "File exceeds maximum size: 10MB" msgstr "" +#: bookwyrm/templatetags/utilities.py:30 +#, python-format +msgid "%(title)s: %(subtitle)s" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "" diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index 54adfb570bf979ce2771021fbb76473b6fc47584..69c734d46688d85bc60fa4b8f060ab0c9fbd8109 100644 GIT binary patch delta 13247 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 H|5gG3Qs!h_ diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index c9a19a4df..fd76f60d4 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-06 20:52+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,99 +18,105 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:224 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "Ya existe un usuario con ese correo electrónico." -#: bookwyrm/forms.py:238 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "Un día" -#: bookwyrm/forms.py:239 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "Una semana" -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "Un mes" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "Nunca se vence" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d usos" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "Sin límite" -#: bookwyrm/forms.py:299 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "Orden de la lista" -#: bookwyrm/forms.py:300 +#: bookwyrm/forms.py:308 msgid "Book Title" msgstr "Título" -#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "Calificación" -#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "Ordenar por" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:315 msgid "Ascending" msgstr "Ascendente" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:316 msgid "Descending" msgstr "Descendente" -#: bookwyrm/models/fields.py:25 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "%(value)s no es un remote_id válido" -#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "%(value)s no es un usuario válido" -#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "nombre de usuario" -#: bookwyrm/models/fields.py:171 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "Ya existe un usuario con ese nombre." -#: bookwyrm/settings.py:156 +#: bookwyrm/settings.py:166 msgid "English" msgstr "Inglés" -#: bookwyrm/settings.py:157 +#: bookwyrm/settings.py:167 msgid "German" msgstr "Aléman" -#: bookwyrm/settings.py:158 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:159 +#: bookwyrm/settings.py:169 msgid "French" msgstr "Francés" -#: bookwyrm/settings.py:160 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "Chino simplificado" +#: bookwyrm/settings.py:171 +#, fuzzy +#| msgid "Additional info:" +msgid "Traditional Chinese" +msgstr "Más informacion:" + #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" msgstr "No encontrado" @@ -136,34 +142,44 @@ msgstr "¡Algo salió mal! Disculpa." msgid "Edit Author" msgstr "Editar Autor/Autora" -#: bookwyrm/templates/author/author.html:32 -#: bookwyrm/templates/author/edit_author.html:38 +#: bookwyrm/templates/author/author.html:34 +#: bookwyrm/templates/author/edit_author.html:41 msgid "Aliases:" msgstr "Aliases:" -#: bookwyrm/templates/author/author.html:38 +#: bookwyrm/templates/author/author.html:45 msgid "Born:" msgstr "Nacido:" -#: bookwyrm/templates/author/author.html:44 +#: bookwyrm/templates/author/author.html:52 msgid "Died:" msgstr "Muerto:" -#: bookwyrm/templates/author/author.html:51 +#: bookwyrm/templates/author/author.html:61 msgid "Wikipedia" msgstr "Wikipedia" -#: bookwyrm/templates/author/author.html:55 -#: bookwyrm/templates/book/book.html:78 +#: bookwyrm/templates/author/author.html:69 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "Ver en OpenLibrary" -#: bookwyrm/templates/author/author.html:60 -#: bookwyrm/templates/book/book.html:81 +#: bookwyrm/templates/author/author.html:77 +#: bookwyrm/templates/book/book.html:98 msgid "View on Inventaire" msgstr "Ver en Inventaire" -#: bookwyrm/templates/author/author.html:74 +#: bookwyrm/templates/author/author.html:85 +#, fuzzy +#| msgid "View on OpenLibrary" +msgid "View on LibraryThing" +msgstr "Ver en OpenLibrary" + +#: bookwyrm/templates/author/author.html:93 +msgid "View on Goodreads" +msgstr "" + +#: bookwyrm/templates/author/author.html:108 #, python-format msgid "Books by %(name)s" msgstr "Libros de %(name)s" @@ -173,213 +189,213 @@ msgid "Edit Author:" msgstr "Editar Autor/Autora/Autore:" #: bookwyrm/templates/author/edit_author.html:13 -#: bookwyrm/templates/book/edit_book.html:18 +#: bookwyrm/templates/book/edit_book.html:19 msgid "Added:" msgstr "Agregado:" #: bookwyrm/templates/author/edit_author.html:14 -#: bookwyrm/templates/book/edit_book.html:19 +#: bookwyrm/templates/book/edit_book.html:24 msgid "Updated:" msgstr "Actualizado:" #: bookwyrm/templates/author/edit_author.html:15 -#: bookwyrm/templates/book/edit_book.html:20 +#: bookwyrm/templates/book/edit_book.html:30 msgid "Last edited by:" msgstr "Editado más recientemente por:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:90 +#: bookwyrm/templates/book/edit_book.html:117 msgid "Metadata" msgstr "Metadatos" -#: bookwyrm/templates/author/edit_author.html:32 +#: bookwyrm/templates/author/edit_author.html:33 #: bookwyrm/templates/lists/form.html:8 #: bookwyrm/templates/user/shelf/create_shelf_form.html:13 #: bookwyrm/templates/user/shelf/edit_shelf_form.html:14 msgid "Name:" msgstr "Nombre:" -#: bookwyrm/templates/author/edit_author.html:40 -#: bookwyrm/templates/book/edit_book.html:132 -#: bookwyrm/templates/book/edit_book.html:141 -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/author/edit_author.html:43 +#: bookwyrm/templates/book/edit_book.html:162 +#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:214 msgid "Separate multiple values with commas." msgstr "Separar varios valores con comas." -#: bookwyrm/templates/author/edit_author.html:46 +#: bookwyrm/templates/author/edit_author.html:50 msgid "Bio:" msgstr "Bio:" -#: bookwyrm/templates/author/edit_author.html:51 +#: bookwyrm/templates/author/edit_author.html:57 msgid "Wikipedia link:" msgstr "Enlace de Wikipedia:" -#: bookwyrm/templates/author/edit_author.html:57 +#: bookwyrm/templates/author/edit_author.html:63 msgid "Birth date:" msgstr "Fecha de nacimiento:" -#: bookwyrm/templates/author/edit_author.html:65 +#: bookwyrm/templates/author/edit_author.html:71 msgid "Death date:" msgstr "Fecha de muerte:" -#: bookwyrm/templates/author/edit_author.html:73 +#: bookwyrm/templates/author/edit_author.html:79 msgid "Author Identifiers" msgstr "Identificadores de autor/autora" -#: bookwyrm/templates/author/edit_author.html:74 +#: bookwyrm/templates/author/edit_author.html:81 msgid "Openlibrary key:" msgstr "Clave OpenLibrary:" -#: bookwyrm/templates/author/edit_author.html:79 -#: bookwyrm/templates/book/edit_book.html:243 +#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/book/edit_book.html:293 msgid "Inventaire ID:" msgstr "ID Inventaire:" -#: bookwyrm/templates/author/edit_author.html:84 +#: bookwyrm/templates/author/edit_author.html:97 msgid "Librarything key:" msgstr "Clave Librarything:" -#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/author/edit_author.html:105 msgid "Goodreads key:" msgstr "Clave Goodreads:" -#: bookwyrm/templates/author/edit_author.html:98 -#: bookwyrm/templates/book/book.html:124 -#: bookwyrm/templates/book/edit_book.html:263 +#: bookwyrm/templates/author/edit_author.html:116 +#: bookwyrm/templates/book/book.html:141 +#: bookwyrm/templates/book/edit_book.html:321 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: 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 -#: bookwyrm/templates/snippets/readthrough.html:77 +#: bookwyrm/templates/settings/site.html:101 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Guardar" -#: bookwyrm/templates/author/edit_author.html:99 -#: bookwyrm/templates/book/book.html:125 bookwyrm/templates/book/book.html:174 +#: bookwyrm/templates/author/edit_author.html:117 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:264 +#: bookwyrm/templates/book/edit_book.html:322 +#: bookwyrm/templates/book/readthrough.html:78 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:78 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:37 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 msgid "Cancel" msgstr "Cancelar" -#: bookwyrm/templates/book/book.html:31 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "por" -#: bookwyrm/templates/book/book.html:39 bookwyrm/templates/book/book.html:40 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "Editar Libro" -#: bookwyrm/templates/book/book.html:57 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "Agregar portada" -#: bookwyrm/templates/book/book.html:61 +#: bookwyrm/templates/book/book.html:78 msgid "Failed to load cover" msgstr "No se pudo cargar la portada" -#: bookwyrm/templates/book/book.html:101 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s reseña)" msgstr[1] "(%(review_count)s reseñas)" -#: bookwyrm/templates/book/book.html:113 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "Agregar descripción" -#: bookwyrm/templates/book/book.html:120 -#: bookwyrm/templates/book/edit_book.html:108 +#: bookwyrm/templates/book/book.html:137 +#: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Descripción:" -#: bookwyrm/templates/book/book.html:134 +#: bookwyrm/templates/book/book.html:151 #, python-format msgid "%(count)s editions" msgstr "%(count)s ediciones" -#: bookwyrm/templates/book/book.html:142 +#: bookwyrm/templates/book/book.html:159 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "Esta edición está en tu %(shelf_name)s estante." -#: bookwyrm/templates/book/book.html:148 +#: bookwyrm/templates/book/book.html:165 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "Una edición diferente de este libro está en tu %(shelf_name)s estante." -#: bookwyrm/templates/book/book.html:159 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "Tu actividad de lectura" -#: bookwyrm/templates/book/book.html:162 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "Agregar fechas de lectura" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "Crear" -#: bookwyrm/templates/book/book.html:181 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "No tienes ninguna actividad de lectura para este libro." -#: bookwyrm/templates/book/book.html:200 +#: bookwyrm/templates/book/book.html:217 msgid "Reviews" msgstr "Reseñas" -#: bookwyrm/templates/book/book.html:205 +#: bookwyrm/templates/book/book.html:222 msgid "Your reviews" msgstr "Tus reseñas" -#: bookwyrm/templates/book/book.html:211 +#: bookwyrm/templates/book/book.html:228 msgid "Your comments" msgstr "Tus comentarios" -#: bookwyrm/templates/book/book.html:217 +#: bookwyrm/templates/book/book.html:234 msgid "Your quotes" msgstr "Tus citas" -#: bookwyrm/templates/book/book.html:253 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "Sujetos" -#: bookwyrm/templates/book/book.html:265 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "Lugares" -#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:68 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "Listas" -#: bookwyrm/templates/book/book.html:287 +#: bookwyrm/templates/book/book.html:304 msgid "Add to list" msgstr "Agregar a lista" -#: bookwyrm/templates/book/book.html:297 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -390,22 +406,22 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:301 msgid "OCLC Number:" msgstr "Número OCLC:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:253 +#: bookwyrm/templates/book/edit_book.html:309 msgid "ASIN:" msgstr "ASIN:" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:192 +#: bookwyrm/templates/book/edit_book.html:229 msgid "Upload cover:" msgstr "Subir portada:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:198 +#: bookwyrm/templates/book/edit_book.html:235 msgid "Load cover from url:" msgstr "Agregar portada de url:" @@ -420,127 +436,134 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Agregar libro" -#: bookwyrm/templates/book/edit_book.html:40 +#: bookwyrm/templates/book/edit_book.html:54 msgid "Confirm Book Info" msgstr "Confirmar información de libro" -#: bookwyrm/templates/book/edit_book.html:47 +#: bookwyrm/templates/book/edit_book.html:62 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "¿Es \"%(name)s\" un autor ya existente?" -#: bookwyrm/templates/book/edit_book.html:52 +#: bookwyrm/templates/book/edit_book.html:71 #, python-format msgid "Author of %(book_title)s" msgstr "Autor de %(book_title)s" -#: bookwyrm/templates/book/edit_book.html:55 +#: bookwyrm/templates/book/edit_book.html:75 msgid "This is a new author" msgstr "Este es un autor nuevo" -#: bookwyrm/templates/book/edit_book.html:61 +#: bookwyrm/templates/book/edit_book.html:82 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creando un autor nuevo: %(name)s" -#: bookwyrm/templates/book/edit_book.html:67 +#: bookwyrm/templates/book/edit_book.html:89 msgid "Is this an edition of an existing work?" msgstr "¿Es esta una edición de una obra ya existente?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:97 msgid "This is a new work" msgstr "Esta es una obra nueva" -#: bookwyrm/templates/book/edit_book.html:77 +#: bookwyrm/templates/book/edit_book.html:104 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "Confirmar" -#: bookwyrm/templates/book/edit_book.html:79 +#: bookwyrm/templates/book/edit_book.html:106 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "Volver" -#: bookwyrm/templates/book/edit_book.html:93 +#: bookwyrm/templates/book/edit_book.html:120 msgid "Title:" msgstr "Título:" -#: bookwyrm/templates/book/edit_book.html:101 +#: bookwyrm/templates/book/edit_book.html:128 msgid "Subtitle:" msgstr "Subtítulo:" -#: bookwyrm/templates/book/edit_book.html:114 +#: bookwyrm/templates/book/edit_book.html:144 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:122 +#: bookwyrm/templates/book/edit_book.html:152 msgid "Series number:" msgstr "Número de serie:" -#: bookwyrm/templates/book/edit_book.html:130 +#: bookwyrm/templates/book/edit_book.html:160 msgid "Languages:" msgstr "Idiomas:" -#: bookwyrm/templates/book/edit_book.html:139 +#: bookwyrm/templates/book/edit_book.html:169 msgid "Publisher:" msgstr "Editorial:" -#: bookwyrm/templates/book/edit_book.html:148 +#: bookwyrm/templates/book/edit_book.html:178 msgid "First published date:" msgstr "Fecha de primera publicación:" -#: bookwyrm/templates/book/edit_book.html:156 +#: bookwyrm/templates/book/edit_book.html:186 msgid "Published date:" msgstr "Fecha de publicación:" -#: bookwyrm/templates/book/edit_book.html:165 +#: bookwyrm/templates/book/edit_book.html:195 msgid "Authors" msgstr "Autores" -#: bookwyrm/templates/book/edit_book.html:171 -#, python-format -msgid "Remove %(name)s" -msgstr "Eliminar %(name)s" +#: bookwyrm/templates/book/edit_book.html:202 +#, fuzzy, python-format +#| msgid "Remove from %(name)s" +msgid "Remove %(name)s" +msgstr "Quitar de %(name)s" -#: bookwyrm/templates/book/edit_book.html:176 +#: bookwyrm/templates/book/edit_book.html:205 +#, fuzzy, python-format +#| msgid "Remove from %(name)s" +msgid "Author page for %(name)s" +msgstr "Quitar de %(name)s" + +#: bookwyrm/templates/book/edit_book.html:212 msgid "Add Authors:" msgstr "Agregar Autores:" -#: bookwyrm/templates/book/edit_book.html:177 +#: bookwyrm/templates/book/edit_book.html:213 msgid "John Doe, Jane Smith" msgstr "Juan Nadie, Natalia Natalia" -#: bookwyrm/templates/book/edit_book.html:183 +#: bookwyrm/templates/book/edit_book.html:220 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "Portada:" -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:248 msgid "Physical Properties" msgstr "Propiedades físicas:" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:250 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "Formato:" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:258 msgid "Pages:" msgstr "Páginas:" -#: bookwyrm/templates/book/edit_book.html:227 +#: bookwyrm/templates/book/edit_book.html:267 msgid "Book Identifiers" msgstr "Identificadores de libro" -#: bookwyrm/templates/book/edit_book.html:228 +#: bookwyrm/templates/book/edit_book.html:269 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:233 +#: bookwyrm/templates/book/edit_book.html:277 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:238 +#: bookwyrm/templates/book/edit_book.html:285 msgid "Openlibrary ID:" msgstr "ID OpenLibrary:" @@ -602,11 +625,40 @@ msgstr "Publicado por %(publisher)s." msgid "rated it" msgstr "lo calificó con" +#: bookwyrm/templates/book/readthrough.html:8 +msgid "Progress Updates:" +msgstr "Actualizaciones de progreso:" + +#: bookwyrm/templates/book/readthrough.html:14 +msgid "finished" +msgstr "terminado" + +#: bookwyrm/templates/book/readthrough.html:25 +msgid "Show all updates" +msgstr "Mostrar todas las actualizaciones" + +#: bookwyrm/templates/book/readthrough.html:41 +msgid "Delete this progress update" +msgstr "Eliminar esta actualización de progreso" + +#: bookwyrm/templates/book/readthrough.html:52 +msgid "started" +msgstr "empezado" + +#: bookwyrm/templates/book/readthrough.html:59 +#: bookwyrm/templates/book/readthrough.html:73 +msgid "Edit read dates" +msgstr "Editar fechas de lectura" + +#: bookwyrm/templates/book/readthrough.html:63 +msgid "Delete these read dates" +msgstr "Eliminar estas fechas de lectura" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:69 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -630,7 +682,7 @@ msgstr "Comunidad federalizada" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "Directorio" @@ -661,23 +713,32 @@ msgstr "Sugerido" msgid "Recently active" msgstr "Activ@ recientemente" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +#, fuzzy +#| msgid "Your Account" +msgid "Locked account" +msgstr "Tu cuenta" + +#: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" msgid_plural "followers you follow" msgstr[0] "seguidor que tu sigues" msgstr[1] "seguidores que tu sigues" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 msgid "book on your shelves" msgid_plural "books on your shelves" msgstr[0] "libro en tus estantes" msgstr[1] "libro en tus estantes" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "publicaciones" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "actividad reciente" @@ -713,7 +774,7 @@ msgid "Recent Books" msgstr "Libros recientes" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "Bienvenidos" @@ -831,7 +892,7 @@ msgid "Direct Messages with %(username)s" msgstr "Mensajes directos con %(username)s" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "Mensajes directos" @@ -873,63 +934,49 @@ msgstr "Federalizado" msgid "load 0 unread status(es)" msgstr "cargar 0 status(es) no leídos" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "¡No hay actividad ahora mismo! Sigue a otro usuario para empezar" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "A quién seguir" - -#: bookwyrm/templates/feed/feed_layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "Actualizaciones" -#: bookwyrm/templates/feed/feed_layout.html:10 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "Tus libros" -#: bookwyrm/templates/feed/feed_layout.html:12 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "¡No hay ningún libro aqui ahorita! Busca a un libro para empezar" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "To Read" msgstr "Para leer" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Currently Reading" msgstr "Leyendo actualmente" -#: bookwyrm/templates/feed/feed_layout.html:25 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13 +#: bookwyrm/templates/feed/layout.html:27 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "Leido" -#: bookwyrm/templates/feed/feed_layout.html:87 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "%(year)s Meta de lectura" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "%(mutuals)s seguidor que sigues" -msgstr[1] "%(mutuals)s seguidores que sigues" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "%(shared_books)s libro en tus estantes" -msgstr[1] "%(shared_books)s libros en tus estantes" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "A quién seguir" #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format @@ -960,7 +1007,7 @@ msgstr "Puedes agregar libros cuando comiences a usar %(site_name)s." #: bookwyrm/templates/get_started/books.html:17 #: 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/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -986,33 +1033,33 @@ msgstr "No se encontró ningún libro" msgid "Save & continue" msgstr "Guardar & continuar" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, python-format msgid "Welcome to %(site_name)s!" msgstr "¡Bienvenido a %(site_name)s!" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "Estos son unos primeros pasos para empezar." -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 msgid "Create your profile" msgstr "Crear tu perfil" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 msgid "Add books" msgstr "Agregar libros" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 msgid "Find friends" msgstr "Encontrar amigos" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "Saltar este paso" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 msgid "Finish" msgstr "Terminar" @@ -1041,7 +1088,7 @@ msgid "Manually approve followers:" msgstr "Aprobar seguidores a mano:" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "Mostrar esta cuenta en los usuarios sugeridos:" @@ -1122,70 +1169,87 @@ msgstr "Importaciones recientes" msgid "No recent imports" msgstr "No hay ninguna importación reciente" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "Status de importación" -#: bookwyrm/templates/import_status.html:12 +#: bookwyrm/templates/import_status.html:11 +#, fuzzy +#| msgid "Back to reports" +msgid "Back to imports" +msgstr "Volver a los informes" + +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "Importación ha empezado:" -#: bookwyrm/templates/import_status.html:16 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "Importación ha terminado:" -#: bookwyrm/templates/import_status.html:19 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "TAREA FALLÓ" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "Importación todavia en progreso" -#: bookwyrm/templates/import_status.html:27 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "(¡Refresca para actualizar!)" -#: bookwyrm/templates/import_status.html:34 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "No se pudo cargar" -#: bookwyrm/templates/import_status.html:43 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "Saltar al final de la lista para seleccionar los %(failed_count)s artículos que no se pudieron importar." -#: bookwyrm/templates/import_status.html:78 +#: bookwyrm/templates/import_status.html:62 +#, python-format +msgid "Line %(index)s: %(title)s by %(author)s" +msgstr "" + +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "Seleccionar todo" -#: bookwyrm/templates/import_status.html:81 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "Reintentar ítems" -#: bookwyrm/templates/import_status.html:107 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "Importado exitosamente" -#: bookwyrm/templates/import_status.html:111 +#: bookwyrm/templates/import_status.html:114 +#, fuzzy +#| msgid "Import still in progress." +msgid "Import Progress" +msgstr "Importación todavia en progreso" + +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "Libro" -#: bookwyrm/templates/import_status.html:114 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: bookwyrm/templates/user/shelf/shelf.html:79 #: bookwyrm/templates/user/shelf/shelf.html:99 msgid "Title" msgstr "Título" -#: bookwyrm/templates/import_status.html:117 +#: bookwyrm/templates/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "Autor/Autora" -#: bookwyrm/templates/import_status.html:140 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "Importado" @@ -1215,27 +1279,27 @@ msgstr "Resultados de búsqueda por \"%(query)s\"" msgid "Matching Books" msgstr "Libros correspondientes" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "Buscar un libro o un usuario" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "Menú de navigación central" -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "Actividad" -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:94 msgid "Your Books" msgstr "Tus libros" -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "Configuración" -#: bookwyrm/templates/layout.html:106 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1243,63 +1307,63 @@ msgstr "Configuración" msgid "Invites" msgstr "Invitaciones" -#: bookwyrm/templates/layout.html:113 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "Admin" -#: bookwyrm/templates/layout.html:120 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "Cerrar sesión" -#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "Notificaciones" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nombre de usuario:" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "contraseña" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "Iniciar sesión" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "Unirse" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:213 #, fuzzy #| msgid "About this server" msgid "About this instance" msgstr "Sobre este servidor" -#: bookwyrm/templates/layout.html:210 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "Contactarse con administradores del sitio" -#: bookwyrm/templates/layout.html:214 +#: bookwyrm/templates/layout.html:221 msgid "Documentation" msgstr "Documentación de Django" -#: bookwyrm/templates/layout.html:221 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "Apoyar %(site_name)s en %(support_title)s" -#: bookwyrm/templates/layout.html:225 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm es software de código abierto. Puedes contribuir o reportar problemas en GitHub." @@ -1677,6 +1741,7 @@ msgstr "¡Estás al día!" #: bookwyrm/templates/password_reset.html:23 #: bookwyrm/templates/preferences/change_password.html:18 +#: bookwyrm/templates/preferences/delete_user.html:20 msgid "Confirm password:" msgstr "Confirmar contraseña:" @@ -1690,7 +1755,7 @@ msgstr "Restablecer contraseña" #: bookwyrm/templates/preferences/blocks.html:4 #: bookwyrm/templates/preferences/blocks.html:7 -#: bookwyrm/templates/preferences/preferences_layout.html:26 +#: bookwyrm/templates/preferences/layout.html:30 msgid "Blocked Users" msgstr "Usuarios bloqueados" @@ -1701,7 +1766,7 @@ msgstr "No hay ningún usuario bloqueado actualmente." #: bookwyrm/templates/preferences/change_password.html:4 #: bookwyrm/templates/preferences/change_password.html:7 #: bookwyrm/templates/preferences/change_password.html:21 -#: bookwyrm/templates/preferences/preferences_layout.html:19 +#: bookwyrm/templates/preferences/layout.html:19 msgid "Change Password" msgstr "Cambiar contraseña" @@ -1709,6 +1774,23 @@ msgstr "Cambiar contraseña" msgid "New password:" msgstr "Nueva contraseña:" +#: bookwyrm/templates/preferences/delete_user.html:4 +#: bookwyrm/templates/preferences/delete_user.html:7 +#: bookwyrm/templates/preferences/delete_user.html:26 +#: bookwyrm/templates/preferences/layout.html:23 +#, fuzzy +#| msgid "Create an Account" +msgid "Delete Account" +msgstr "Crear una cuenta" + +#: bookwyrm/templates/preferences/delete_user.html:12 +msgid "Permanently delete account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:14 +msgid "Deleting your account cannot be undone. The username will not be available to register in the future." +msgstr "" + #: bookwyrm/templates/preferences/edit_user.html:4 #: bookwyrm/templates/preferences/edit_user.html:7 msgid "Edit Profile" @@ -1718,44 +1800,68 @@ msgstr "Editar perfil" msgid "Show set reading goal prompt in feed:" msgstr "Mostrar meta de lectura en el feed:" -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +#, fuzzy +#| msgid "Post privacy" +msgid "Default post privacy:" +msgstr "Privacidad de publicación" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm." -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "Huso horario preferido" -#: bookwyrm/templates/preferences/preferences_layout.html:11 +#: bookwyrm/templates/preferences/layout.html:11 msgid "Account" msgstr "Cuenta" -#: bookwyrm/templates/preferences/preferences_layout.html:15 +#: bookwyrm/templates/preferences/layout.html:15 msgid "Profile" msgstr "Perfil" -#: bookwyrm/templates/preferences/preferences_layout.html:22 +#: bookwyrm/templates/preferences/layout.html:26 msgid "Relationships" msgstr "Relaciones" +#: bookwyrm/templates/reading_progress/finish.html:5 +#, fuzzy, python-format +#| msgid "Finish \"%(book_title)s\"" +msgid "Finish \"%(book_title)s\"" +msgstr "Terminar \"%(book_title)s\"" + +#: bookwyrm/templates/reading_progress/start.html:5 +#, fuzzy, python-format +#| msgid "Edit \"%(book_title)s\"" +msgid "Start \"%(book_title)s\"" +msgstr "Editar \"%(book_title)s\"" + +#: bookwyrm/templates/reading_progress/want.html:5 +#, fuzzy, python-format +#| msgid "Want to Read \"%(book_title)s\"" +msgid "Want to Read \"%(book_title)s\"" +msgstr "Quiero leer \"%(book_title)s\"" + #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "calificó" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "reseñó" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "comentó en" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "citó" @@ -1781,7 +1887,7 @@ msgstr "Tipo de búsqueda" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:74 +#: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "Libros" @@ -1992,7 +2098,7 @@ msgid "Details" msgstr "Detalles" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:56 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "Actividad" @@ -2031,7 +2137,7 @@ msgid "Edit" msgstr "Editar" #: bookwyrm/templates/settings/federated_server.html:105 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:8 msgid "Actions" msgstr "Acciones" @@ -2239,15 +2345,19 @@ msgstr "Correo electrónico de administradorx:" msgid "Additional info:" msgstr "Más informacion:" -#: bookwyrm/templates/settings/site.html:83 -msgid "Allow registration:" +#: bookwyrm/templates/settings/site.html:85 +#, fuzzy +#| msgid "Allow registration:" +msgid "Allow registration" msgstr "Permitir registración:" -#: bookwyrm/templates/settings/site.html:87 -msgid "Allow invite requests:" +#: bookwyrm/templates/settings/site.html:91 +#, fuzzy +#| msgid "Allow invite requests:" +msgid "Allow invite requests" msgstr "Permitir solicitudes de invitación:" -#: bookwyrm/templates/settings/site.html:91 +#: bookwyrm/templates/settings/site.html:95 msgid "Registration closed text:" msgstr "Texto de registración cerrada:" @@ -2256,7 +2366,7 @@ msgstr "Texto de registración cerrada:" msgid "Posted by %(username)s" msgstr "Publicado por %(username)s" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "Sin portada" @@ -2344,7 +2454,7 @@ msgstr "Incluir alerta de spoiler" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "Privada" @@ -2461,7 +2571,7 @@ msgstr "Privacidad de meta:" #: bookwyrm/templates/snippets/goal_form.html:26 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:29 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 msgid "Post to feed" msgstr "Compartir con tu feed" @@ -2506,13 +2616,13 @@ msgstr "Siguiente" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "Público" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "Privado" @@ -2524,7 +2634,7 @@ msgstr "Solo seguidores" msgid "Post privacy" msgstr "Privacidad de publicación" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2538,38 +2648,9 @@ msgstr "Da una calificación" msgid "Rate" msgstr "Calificar" -#: bookwyrm/templates/snippets/readthrough.html:8 -msgid "Progress Updates:" -msgstr "Actualizaciones de progreso:" - -#: bookwyrm/templates/snippets/readthrough.html:14 -msgid "finished" -msgstr "terminado" - -#: bookwyrm/templates/snippets/readthrough.html:25 -msgid "Show all updates" -msgstr "Mostrar todas las actualizaciones" - -#: bookwyrm/templates/snippets/readthrough.html:41 -msgid "Delete this progress update" -msgstr "Eliminar esta actualización de progreso" - -#: bookwyrm/templates/snippets/readthrough.html:52 -msgid "started" -msgstr "empezado" - -#: bookwyrm/templates/snippets/readthrough.html:59 -#: bookwyrm/templates/snippets/readthrough.html:73 -msgid "Edit read dates" -msgstr "Editar fechas de lectura" - -#: bookwyrm/templates/snippets/readthrough.html:63 -msgid "Delete these read dates" -msgstr "Eliminar estas fechas de lectura" - #: bookwyrm/templates/snippets/readthrough_form.html:7 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:17 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Lectura se empezó" @@ -2604,7 +2685,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "Terminar \"%(book_title)s\"" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:36 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 msgid "Update progress" msgstr "Progreso de actualización" @@ -2612,20 +2693,20 @@ msgstr "Progreso de actualización" msgid "More shelves" msgstr "Más estantes" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:10 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 msgid "Start reading" msgstr "Empezar leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:15 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 msgid "Finish reading" msgstr "Terminar de leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:18 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 msgid "Want to read" msgstr "Quiero leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 #, python-format msgid "Remove from %(name)s" msgstr "Quitar de %(name)s" @@ -2640,17 +2721,17 @@ msgstr "Empezar \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" msgstr "Quiero leer \"%(book_title)s\"" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "Mostrar más" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "Mostrar menos" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "Abrir imagen en una nueva ventana" @@ -2673,7 +2754,7 @@ msgstr "Me gusta status" msgid "boosted" msgstr "respaldó" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, python-format msgid "replied to %(username)s's status" msgstr "respondió al status de %(username)s " @@ -2689,10 +2770,31 @@ msgstr "Eliminar y recomponer" #: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:12 msgid "Send direct message" msgstr "Enviar mensaje directo" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "%(mutuals)s seguidor que sigues" +msgstr[1] "%(mutuals)s seguidores que sigues" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "%(shared_books)s libro en tus estantes" +msgstr[1] "%(shared_books)s libros en tus estantes" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +#, fuzzy +#| msgid "followed you" +msgid "Follows you" +msgstr "te siguió" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "Cambiar a esta edición" @@ -2705,15 +2807,15 @@ msgstr "En orden ascendente" msgid "Sorted descending" msgstr "En orden descendente" -#: bookwyrm/templates/user/layout.html:13 bookwyrm/templates/user/user.html:10 +#: bookwyrm/templates/user/layout.html:18 bookwyrm/templates/user/user.html:10 msgid "User Profile" msgstr "Perfil de usuario" -#: bookwyrm/templates/user/layout.html:37 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "Solicitudes de seguidor" -#: bookwyrm/templates/user/layout.html:62 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "Meta de lectura" @@ -2819,30 +2921,37 @@ msgstr "Feed RSS" msgid "No activities yet!" msgstr "¡Aún no actividades!" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "Unido %(date)s" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "%(counter)s seguidor" msgstr[1] "%(counter)s seguidores" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "%(counter)s siguiendo" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "%(mutuals_display)s seguidor que sigues" msgstr[1] "%(mutuals_display)s seguidores que sigues" +#: bookwyrm/templates/user/user_preview.html:38 +#, fuzzy +#| msgid "follower you follow" +#| msgid_plural "followers you follow" +msgid "No followers you follow" +msgstr "seguidor que tu sigues" + #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" msgstr "Volver a usuarios" @@ -2900,22 +3009,31 @@ msgstr "Detalles de instancia" msgid "View instance" msgstr "Ver instancia" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:5 +msgid "Permanently deleted" +msgstr "" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:17 msgid "Suspend user" msgstr "Suspender usuario" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:19 msgid "Un-suspend user" msgstr "Des-suspender usuario" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:28 msgid "Access level:" msgstr "Nivel de acceso:" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 msgid "File exceeds maximum size: 10MB" msgstr "" +#: bookwyrm/templatetags/utilities.py:30 +#, python-format +msgid "%(title)s: %(subtitle)s" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "No un archivo csv válido" @@ -2929,6 +3047,9 @@ msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónic msgid "A password reset link sent to %s" msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" +#~ msgid "Remove %(name)s" +#~ msgstr "Eliminar %(name)s" + #~ msgid "Federated Servers" #~ msgstr "Servidores federalizados" diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index d29afc1cf..c4ca623c4 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-09 16:46+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -18,99 +18,105 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:224 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "Cet email est déjà associé à un compte." -#: bookwyrm/forms.py:238 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "Un jour" -#: bookwyrm/forms.py:239 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "Une semaine" -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "Un mois" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "Sans expiration" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d utilisations" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "Sans limite" -#: bookwyrm/forms.py:299 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "Ordre de la liste" -#: bookwyrm/forms.py:300 +#: bookwyrm/forms.py:308 msgid "Book Title" msgstr "Titre du livre" -#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "Note" -#: bookwyrm/forms.py:303 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "Trier par" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:315 msgid "Ascending" msgstr "Ordre croissant" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:316 msgid "Descending" msgstr "Ordre décroissant" -#: bookwyrm/models/fields.py:25 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "%(value)s n’est pas une remote_id valide." -#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "%(value)s n’est pas un nom de compte valide." -#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "nom du compte :" -#: bookwyrm/models/fields.py:171 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "Ce nom est déjà associé à un compte." -#: bookwyrm/settings.py:156 +#: bookwyrm/settings.py:166 msgid "English" msgstr "English" -#: bookwyrm/settings.py:157 +#: bookwyrm/settings.py:167 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:158 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:159 +#: bookwyrm/settings.py:169 msgid "French" msgstr "Français" -#: bookwyrm/settings.py:160 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "简化字" +#: bookwyrm/settings.py:171 +#, fuzzy +#| msgid "Additional info:" +msgid "Traditional Chinese" +msgstr "Infos supplémentaires :" + #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" msgstr "Introuvable" @@ -154,12 +160,12 @@ msgid "Wikipedia" msgstr "Wikipedia" #: bookwyrm/templates/author/author.html:69 -#: bookwyrm/templates/book/book.html:87 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "Voir sur OpenLibrary" #: bookwyrm/templates/author/author.html:77 -#: bookwyrm/templates/book/book.html:90 +#: bookwyrm/templates/book/book.html:98 msgid "View on Inventaire" msgstr "Voir sur Inventaire" @@ -252,142 +258,142 @@ msgid "Goodreads key:" msgstr "Clé Goodreads :" #: bookwyrm/templates/author/edit_author.html:116 -#: bookwyrm/templates/book/book.html:133 +#: bookwyrm/templates/book/book.html:141 #: bookwyrm/templates/book/edit_book.html:321 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: 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:101 -#: bookwyrm/templates/snippets/readthrough.html:77 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Enregistrer" #: bookwyrm/templates/author/edit_author.html:117 -#: bookwyrm/templates/book/book.html:134 bookwyrm/templates/book/book.html:183 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 #: bookwyrm/templates/book/edit_book.html:322 +#: bookwyrm/templates/book/readthrough.html:78 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:78 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:37 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 msgid "Cancel" msgstr "Annuler" -#: bookwyrm/templates/book/book.html:40 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "par" -#: bookwyrm/templates/book/book.html:48 bookwyrm/templates/book/book.html:49 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "Modifier le livre" -#: bookwyrm/templates/book/book.html:66 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "Ajouter une couverture" -#: bookwyrm/templates/book/book.html:70 +#: bookwyrm/templates/book/book.html:78 msgid "Failed to load cover" msgstr "La couverture n’a pu être chargée" -#: bookwyrm/templates/book/book.html:110 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s critique)" msgstr[1] "(%(review_count)s critiques)" -#: bookwyrm/templates/book/book.html:122 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "Ajouter une description" -#: bookwyrm/templates/book/book.html:129 +#: bookwyrm/templates/book/book.html:137 #: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Description :" -#: bookwyrm/templates/book/book.html:143 +#: bookwyrm/templates/book/book.html:151 #, python-format msgid "%(count)s editions" msgstr "%(count)s éditions" -#: bookwyrm/templates/book/book.html:151 +#: bookwyrm/templates/book/book.html:159 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "Cette édition est sur votre étagère %(shelf_name)s." -#: bookwyrm/templates/book/book.html:157 +#: bookwyrm/templates/book/book.html:165 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "Une édition différente de ce livre existe sur votre étagère %(shelf_name)s." -#: bookwyrm/templates/book/book.html:168 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "Votre activité de lecture" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "Ajouter des dates de lecture" -#: bookwyrm/templates/book/book.html:180 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "Créer" -#: bookwyrm/templates/book/book.html:190 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "Vous n’avez aucune activité de lecture pour ce livre" -#: bookwyrm/templates/book/book.html:209 +#: bookwyrm/templates/book/book.html:217 msgid "Reviews" msgstr "Critiques" -#: bookwyrm/templates/book/book.html:214 +#: bookwyrm/templates/book/book.html:222 msgid "Your reviews" msgstr "Vos critiques" -#: bookwyrm/templates/book/book.html:220 +#: bookwyrm/templates/book/book.html:228 msgid "Your comments" msgstr "Vos commentaires" -#: bookwyrm/templates/book/book.html:226 +#: bookwyrm/templates/book/book.html:234 msgid "Your quotes" msgstr "Vos citations" -#: bookwyrm/templates/book/book.html:262 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "Sujets" -#: bookwyrm/templates/book/book.html:274 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "Lieux" -#: bookwyrm/templates/book/book.html:285 bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:68 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "Listes" -#: bookwyrm/templates/book/book.html:296 +#: bookwyrm/templates/book/book.html:304 msgid "Add to list" msgstr "Ajouter à la liste" -#: bookwyrm/templates/book/book.html:306 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -615,11 +621,40 @@ msgstr "Publié par %(publisher)s." msgid "rated it" msgstr "l’a noté" +#: bookwyrm/templates/book/readthrough.html:8 +msgid "Progress Updates:" +msgstr "Progression :" + +#: bookwyrm/templates/book/readthrough.html:14 +msgid "finished" +msgstr "terminé" + +#: bookwyrm/templates/book/readthrough.html:25 +msgid "Show all updates" +msgstr "Montrer toutes les progressions" + +#: bookwyrm/templates/book/readthrough.html:41 +msgid "Delete this progress update" +msgstr "Supprimer cette mise à jour" + +#: bookwyrm/templates/book/readthrough.html:52 +msgid "started" +msgstr "commencé" + +#: bookwyrm/templates/book/readthrough.html:59 +#: bookwyrm/templates/book/readthrough.html:73 +msgid "Edit read dates" +msgstr "Modifier les date de lecture" + +#: bookwyrm/templates/book/readthrough.html:63 +msgid "Delete these read dates" +msgstr "Supprimer ces dates de lecture" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:69 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -643,7 +678,7 @@ msgstr "Communauté fédérée" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "Répertoire" @@ -674,23 +709,32 @@ msgstr "Suggéré" msgid "Recently active" msgstr "Actif récemment" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +#, fuzzy +#| msgid "Your Account" +msgid "Locked account" +msgstr "Votre compte" + +#: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" msgid_plural "followers you follow" msgstr[0] "compte que vous suivez" msgstr[1] "comptes que vous suivez" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 msgid "book on your shelves" msgid_plural "books on your shelves" msgstr[0] "livre sur vos étagères" msgstr[1] "livres sur vos étagères" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "publications" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "dernière activité" @@ -726,7 +770,7 @@ msgid "Recent Books" msgstr "Livres récents" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "Bienvenue" @@ -844,7 +888,7 @@ msgid "Direct Messages with %(username)s" msgstr "Messages directs avec %(username)s" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "Messages directs" @@ -886,63 +930,49 @@ msgstr "Fédéré" msgid "load 0 unread status(es)" msgstr "charger le(s) 0 statut(s) non lu(s)" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "Aucune activité pour l’instant ! Abonnez‑vous à quelqu’un pour commencer" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "À qui s’abonner" - -#: bookwyrm/templates/feed/feed_layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "Mises à jour" -#: bookwyrm/templates/feed/feed_layout.html:10 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "Vos livres" -#: bookwyrm/templates/feed/feed_layout.html:12 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "Aucun livre ici pour l’instant ! Cherchez un livre pour commencer" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "To Read" msgstr "À lire" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Currently Reading" msgstr "Lectures en cours" -#: bookwyrm/templates/feed/feed_layout.html:25 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13 +#: bookwyrm/templates/feed/layout.html:27 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "Lu" -#: bookwyrm/templates/feed/feed_layout.html:87 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "Défi lecture pour %(year)s" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "%(mutuals)s abonné(e) que vous suivez" -msgstr[1] "%(mutuals)s abonné(e)s que vous suivez" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "%(shared_books)s livre sur vos étagères" -msgstr[1] "%(shared_books)s livres sur vos étagères" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "À qui s’abonner" #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format @@ -973,7 +1003,7 @@ msgstr "Vous pourrez ajouter des livres lorsque vous commencerez à utiliser %(s #: bookwyrm/templates/get_started/books.html:17 #: 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/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -999,33 +1029,33 @@ msgstr "Aucun livre trouvé" msgid "Save & continue" msgstr "Enregistrer & continuer" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, python-format msgid "Welcome to %(site_name)s!" msgstr "Bienvenue sur %(site_name)s !" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "Voici quelques étapes pour commencer votre profil." -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 msgid "Create your profile" msgstr "Créez votre profil" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 msgid "Add books" msgstr "Ajoutez des livres" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 msgid "Find friends" msgstr "Établissez des contacts" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "Passer cette étape" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 msgid "Finish" msgstr "Terminer" @@ -1054,7 +1084,7 @@ msgid "Manually approve followers:" msgstr "Autoriser les abonnements manuellement :" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "Afficher ce compte dans ceux suggérés :" @@ -1135,75 +1165,87 @@ msgstr "Importations récentes" msgid "No recent imports" msgstr "Aucune importation récente" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "Statut de l’importation" -#: bookwyrm/templates/import_status.html:13 +#: bookwyrm/templates/import_status.html:11 +#, fuzzy +#| msgid "Back to reports" +msgid "Back to imports" +msgstr "Retour aux signalements" + +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "Début de l’importation :" -#: bookwyrm/templates/import_status.html:18 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "Fin de l’importation :" -#: bookwyrm/templates/import_status.html:23 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "la tâche a échoué" -#: bookwyrm/templates/import_status.html:30 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "L’importation est toujours en cours" -#: bookwyrm/templates/import_status.html:32 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "(Rechargez la page pour la mettre à jour !)" -#: bookwyrm/templates/import_status.html:39 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "Éléments non importés" -#: bookwyrm/templates/import_status.html:48 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "Sauter en bas de liste pour sélectionner les %(failed_count)s items n’ayant pu être importés." -#: bookwyrm/templates/import_status.html:60 +#: bookwyrm/templates/import_status.html:62 #, python-format msgid "Line %(index)s: %(title)s by %(author)s" msgstr "Ligne %(index)s : %(title)s par %(author)s" -#: bookwyrm/templates/import_status.html:80 +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "Tout sélectionner" -#: bookwyrm/templates/import_status.html:83 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "Réessayer l’importation de ces éléments" -#: bookwyrm/templates/import_status.html:109 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "Importation réussie" -#: bookwyrm/templates/import_status.html:113 +#: bookwyrm/templates/import_status.html:114 +#, fuzzy +#| msgid "Import still in progress." +msgid "Import Progress" +msgstr "L’importation est toujours en cours" + +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "Livre" -#: bookwyrm/templates/import_status.html:116 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: bookwyrm/templates/user/shelf/shelf.html:79 #: bookwyrm/templates/user/shelf/shelf.html:99 msgid "Title" msgstr "Titre" -#: bookwyrm/templates/import_status.html:119 +#: bookwyrm/templates/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "Auteur/autrice" -#: bookwyrm/templates/import_status.html:142 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "Importé" @@ -1233,27 +1275,27 @@ msgstr "Résultats de recherche pour « %(query)s »" msgid "Matching Books" msgstr "Livres correspondants" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "Chercher un livre ou un compte" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "Menu de navigation principal " -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "Fil d’actualité" -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:94 msgid "Your Books" msgstr "Vos Livres" -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "Paramètres" -#: bookwyrm/templates/layout.html:106 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1261,61 +1303,61 @@ msgstr "Paramètres" msgid "Invites" msgstr "Invitations" -#: bookwyrm/templates/layout.html:113 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "Admin" -#: bookwyrm/templates/layout.html:120 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "Se déconnecter" -#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "Notifications" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nom du compte :" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "Mot de passe" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "Mot de passe oublié ?" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "Se connecter" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "Rejoindre" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:213 msgid "About this instance" msgstr "À propos de cette instance" -#: bookwyrm/templates/layout.html:210 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "Contacter l’administrateur du site" -#: bookwyrm/templates/layout.html:214 +#: bookwyrm/templates/layout.html:221 msgid "Documentation" msgstr "Documentation" -#: bookwyrm/templates/layout.html:221 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "Soutenez %(site_name)s avec %(support_title)s" -#: bookwyrm/templates/layout.html:225 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm est un logiciel libre. Vous pouvez contribuer ou faire des rapports de bogues via GitHub." @@ -1693,6 +1735,7 @@ msgstr "Aucune nouvelle notification !" #: bookwyrm/templates/password_reset.html:23 #: bookwyrm/templates/preferences/change_password.html:18 +#: bookwyrm/templates/preferences/delete_user.html:20 msgid "Confirm password:" msgstr "Confirmez le mot de passe :" @@ -1706,7 +1749,7 @@ msgstr "Changer de mot de passe" #: bookwyrm/templates/preferences/blocks.html:4 #: bookwyrm/templates/preferences/blocks.html:7 -#: bookwyrm/templates/preferences/preferences_layout.html:26 +#: bookwyrm/templates/preferences/layout.html:30 msgid "Blocked Users" msgstr "Comptes bloqués" @@ -1717,7 +1760,7 @@ msgstr "Aucun compte bloqué actuellement" #: bookwyrm/templates/preferences/change_password.html:4 #: bookwyrm/templates/preferences/change_password.html:7 #: bookwyrm/templates/preferences/change_password.html:21 -#: bookwyrm/templates/preferences/preferences_layout.html:19 +#: bookwyrm/templates/preferences/layout.html:19 msgid "Change Password" msgstr "Changer le mot de passe" @@ -1725,6 +1768,23 @@ msgstr "Changer le mot de passe" msgid "New password:" msgstr "Nouveau mot de passe :" +#: bookwyrm/templates/preferences/delete_user.html:4 +#: bookwyrm/templates/preferences/delete_user.html:7 +#: bookwyrm/templates/preferences/delete_user.html:26 +#: bookwyrm/templates/preferences/layout.html:23 +#, fuzzy +#| msgid "Create an Account" +msgid "Delete Account" +msgstr "Créer un compte" + +#: bookwyrm/templates/preferences/delete_user.html:12 +msgid "Permanently delete account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:14 +msgid "Deleting your account cannot be undone. The username will not be available to register in the future." +msgstr "" + #: bookwyrm/templates/preferences/edit_user.html:4 #: bookwyrm/templates/preferences/edit_user.html:7 msgid "Edit Profile" @@ -1734,44 +1794,68 @@ msgstr "Modifier le profil" msgid "Show set reading goal prompt in feed:" msgstr "Afficher le message pour définir un défi lecture dans le fil d’actualité :" -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +#, fuzzy +#| msgid "Post privacy" +msgid "Default post privacy:" +msgstr "Confidentialité du statut" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "Votre compte sera listé dans le répertoire et pourra être recommandé à d’autres utilisateurs ou utilisatrices de BookWyrm." -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "Fuseau horaire préféré" -#: bookwyrm/templates/preferences/preferences_layout.html:11 +#: bookwyrm/templates/preferences/layout.html:11 msgid "Account" msgstr "Compte" -#: bookwyrm/templates/preferences/preferences_layout.html:15 +#: bookwyrm/templates/preferences/layout.html:15 msgid "Profile" msgstr "Profil" -#: bookwyrm/templates/preferences/preferences_layout.html:22 +#: bookwyrm/templates/preferences/layout.html:26 msgid "Relationships" msgstr "Relations" +#: bookwyrm/templates/reading_progress/finish.html:5 +#, fuzzy, python-format +#| msgid "Finish \"%(book_title)s\"" +msgid "Finish \"%(book_title)s\"" +msgstr "Terminer « %(book_title)s »" + +#: bookwyrm/templates/reading_progress/start.html:5 +#, fuzzy, python-format +#| msgid "Edit \"%(book_title)s\"" +msgid "Start \"%(book_title)s\"" +msgstr "Modifier « %(book_title)s »" + +#: bookwyrm/templates/reading_progress/want.html:5 +#, fuzzy, python-format +#| msgid "Want to Read \"%(book_title)s\"" +msgid "Want to Read \"%(book_title)s\"" +msgstr "Ajouter « %(book_title)s » aux envies de lecture" + #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "a noté" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "a écrit une critique de" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "a commenté" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "a cité" @@ -1797,7 +1881,7 @@ msgstr "Type de recherche" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:74 +#: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "Livres" @@ -2002,7 +2086,7 @@ msgid "Details" msgstr "Détails" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:56 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "Activité" @@ -2041,7 +2125,7 @@ msgid "Edit" msgstr "Modifier" #: bookwyrm/templates/settings/federated_server.html:105 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:8 msgid "Actions" msgstr "Actions" @@ -2264,7 +2348,7 @@ msgstr "Texte affiché lorsque les inscriptions sont closes :" msgid "Posted by %(username)s" msgstr "Publiée par %(username)s" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "Pas de couverture" @@ -2352,7 +2436,7 @@ msgstr "Afficher une alerte spoiler" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "Privé" @@ -2469,7 +2553,7 @@ msgstr "Confidentialité du défi :" #: bookwyrm/templates/snippets/goal_form.html:26 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:29 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 msgid "Post to feed" msgstr "Publier sur le fil d’actualité" @@ -2513,13 +2597,13 @@ msgstr "Suivante" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "Public" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "Non listé" @@ -2531,7 +2615,7 @@ msgstr "Abonnemé(e)s uniquement" msgid "Post privacy" msgstr "Confidentialité du statut" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2545,38 +2629,9 @@ msgstr "Laisser une note" msgid "Rate" msgstr "Noter" -#: bookwyrm/templates/snippets/readthrough.html:8 -msgid "Progress Updates:" -msgstr "Progression :" - -#: bookwyrm/templates/snippets/readthrough.html:14 -msgid "finished" -msgstr "terminé" - -#: bookwyrm/templates/snippets/readthrough.html:25 -msgid "Show all updates" -msgstr "Montrer toutes les progressions" - -#: bookwyrm/templates/snippets/readthrough.html:41 -msgid "Delete this progress update" -msgstr "Supprimer cette mise à jour" - -#: bookwyrm/templates/snippets/readthrough.html:52 -msgid "started" -msgstr "commencé" - -#: bookwyrm/templates/snippets/readthrough.html:59 -#: bookwyrm/templates/snippets/readthrough.html:73 -msgid "Edit read dates" -msgstr "Modifier les date de lecture" - -#: bookwyrm/templates/snippets/readthrough.html:63 -msgid "Delete these read dates" -msgstr "Supprimer ces dates de lecture" - #: bookwyrm/templates/snippets/readthrough_form.html:7 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:17 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Lecture commencée le" @@ -2611,7 +2666,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "Terminer « %(book_title)s »" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:36 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 msgid "Update progress" msgstr "Progression de la mise à jour" @@ -2619,20 +2674,20 @@ msgstr "Progression de la mise à jour" msgid "More shelves" msgstr "Plus d’étagères" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:10 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 msgid "Start reading" msgstr "Commencer la lecture" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:15 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 msgid "Finish reading" msgstr "Terminer la lecture" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:18 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 msgid "Want to read" msgstr "Je veux le lire" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 #, python-format msgid "Remove from %(name)s" msgstr "Retirer de %(name)s" @@ -2647,17 +2702,17 @@ msgstr "Commencer « %(book_title)s »" msgid "Want to Read \"%(book_title)s\"" msgstr "Ajouter « %(book_title)s » aux envies de lecture" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "Déplier" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "Replier" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "Ouvrir l’image dans une nouvelle fenêtre" @@ -2680,7 +2735,7 @@ msgstr "Ajouter le statut aux favoris" msgid "boosted" msgstr "a partagé" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, python-format msgid "replied to %(username)s's status" msgstr "a répondu au statut de %(username)s" @@ -2696,10 +2751,31 @@ msgstr "Supprimer & recommencer la rédaction" #: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:12 msgid "Send direct message" msgstr "Envoyer un message direct" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "%(mutuals)s abonné(e) que vous suivez" +msgstr[1] "%(mutuals)s abonné(e)s que vous suivez" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "%(shared_books)s livre sur vos étagères" +msgstr[1] "%(shared_books)s livres sur vos étagères" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +#, fuzzy +#| msgid "followed you" +msgid "Follows you" +msgstr "vous suit" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "Changer vers cette édition" @@ -2712,15 +2788,15 @@ msgstr "Trié par ordre croissant" msgid "Sorted descending" msgstr "Trié par ordre décroissant" -#: bookwyrm/templates/user/layout.html:13 bookwyrm/templates/user/user.html:10 +#: bookwyrm/templates/user/layout.html:18 bookwyrm/templates/user/user.html:10 msgid "User Profile" msgstr "Profil" -#: bookwyrm/templates/user/layout.html:37 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "Demandes d’abonnement" -#: bookwyrm/templates/user/layout.html:62 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "Défi lecture" @@ -2826,30 +2902,37 @@ msgstr "Flux RSS" msgid "No activities yet!" msgstr "Aucune activité pour l’instant !" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "A rejoint ce serveur %(date)s" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "%(counter)s abonné(e)" msgstr[1] "%(counter)s abonné(e)s" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "%(counter)s abonnements" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "%(mutuals_display)s abonné(e) que vous suivez" msgstr[1] "%(mutuals_display)s abonné(e)s que vous suivez" +#: bookwyrm/templates/user/user_preview.html:38 +#, fuzzy +#| msgid "follower you follow" +#| msgid_plural "followers you follow" +msgid "No followers you follow" +msgstr "compte que vous suivez" + #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" msgstr "Retour aux comptes" @@ -2905,15 +2988,19 @@ msgstr "Détails de l’instance" msgid "View instance" msgstr "Voir l’instance" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:5 +msgid "Permanently deleted" +msgstr "" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:17 msgid "Suspend user" msgstr "Suspendre le compte" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:19 msgid "Un-suspend user" msgstr "Rétablir le compte" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:28 msgid "Access level:" msgstr "Niveau d’accès :" diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index a52542b0a..f74dfd4a7 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-30 09:07+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -18,100 +18,100 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: bookwyrm/forms.py:231 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "已经存在使用该邮箱的用户。" -#: bookwyrm/forms.py:245 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "一天" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "一周" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "一个月" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "永不失效" -#: bookwyrm/forms.py:253 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d 次使用" -#: bookwyrm/forms.py:256 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "不受限" -#: bookwyrm/forms.py:306 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "列表顺序" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "Book Title" msgstr "书名" -#: bookwyrm/forms.py:308 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "评价" -#: bookwyrm/forms.py:310 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "排序方式" -#: bookwyrm/forms.py:314 +#: bookwyrm/forms.py:315 msgid "Ascending" msgstr "升序" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Descending" msgstr "降序" -#: bookwyrm/models/fields.py:26 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "%(value)s 不是有效的 remote_id" -#: bookwyrm/models/fields.py:35 bookwyrm/models/fields.py:44 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "%(value)s 不是有效的用户名" -#: bookwyrm/models/fields.py:167 bookwyrm/templates/layout.html:157 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "用户名" -#: bookwyrm/models/fields.py:172 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "已经存在使用该用户名的用户。" -#: bookwyrm/settings.py:164 +#: bookwyrm/settings.py:166 msgid "English" msgstr "English(英语)" -#: bookwyrm/settings.py:165 +#: bookwyrm/settings.py:167 msgid "German" msgstr "Deutsch(德语)" -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "Español(西班牙语)" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:169 msgid "French" msgstr "Français(法语)" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "简体中文" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:171 msgid "Traditional Chinese" msgstr "繁體中文(繁体中文)" @@ -158,12 +158,12 @@ msgid "Wikipedia" msgstr "维基百科" #: bookwyrm/templates/author/author.html:69 -#: bookwyrm/templates/book/book.html:90 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "在 OpenLibrary 查看" #: bookwyrm/templates/author/author.html:77 -#: bookwyrm/templates/book/book.html:93 +#: bookwyrm/templates/book/book.html:98 msgid "View on Inventaire" msgstr "在 Inventaire 查看" @@ -256,11 +256,11 @@ msgid "Goodreads key:" msgstr "Goodreads key:" #: bookwyrm/templates/author/edit_author.html:116 -#: bookwyrm/templates/book/book.html:136 +#: bookwyrm/templates/book/book.html:141 #: bookwyrm/templates/book/edit_book.html:321 #: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 @@ -273,7 +273,7 @@ msgid "Save" msgstr "保存" #: bookwyrm/templates/author/edit_author.html:117 -#: bookwyrm/templates/book/book.html:137 bookwyrm/templates/book/book.html:186 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 #: bookwyrm/templates/book/edit_book.html:322 #: bookwyrm/templates/book/readthrough.html:78 @@ -288,109 +288,109 @@ msgstr "保存" msgid "Cancel" msgstr "取消" -#: bookwyrm/templates/book/book.html:43 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "作者" -#: bookwyrm/templates/book/book.html:51 bookwyrm/templates/book/book.html:52 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "编辑书目" -#: bookwyrm/templates/book/book.html:69 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "添加封面" -#: bookwyrm/templates/book/book.html:73 +#: bookwyrm/templates/book/book.html:78 msgid "Failed to load cover" msgstr "加载封面失败" -#: bookwyrm/templates/book/book.html:113 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s 则书评)" -#: bookwyrm/templates/book/book.html:125 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "添加描述" -#: bookwyrm/templates/book/book.html:132 +#: bookwyrm/templates/book/book.html:137 #: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "描述:" -#: bookwyrm/templates/book/book.html:146 +#: bookwyrm/templates/book/book.html:151 #, python-format msgid "%(count)s editions" msgstr "%(count)s 个版本" -#: bookwyrm/templates/book/book.html:154 +#: bookwyrm/templates/book/book.html:159 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "此版本在你的 %(shelf_name)s 书架上。" -#: bookwyrm/templates/book/book.html:160 +#: bookwyrm/templates/book/book.html:165 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "本书的 另一个版本 在你的 %(shelf_name)s 书架上。" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "你的阅读活动" -#: bookwyrm/templates/book/book.html:174 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "添加阅读日期" -#: bookwyrm/templates/book/book.html:183 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "创建" -#: bookwyrm/templates/book/book.html:193 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "你还没有任何这本书的阅读活动。" -#: bookwyrm/templates/book/book.html:212 +#: bookwyrm/templates/book/book.html:217 msgid "Reviews" msgstr "书评" -#: bookwyrm/templates/book/book.html:217 +#: bookwyrm/templates/book/book.html:222 msgid "Your reviews" msgstr "你的书评" -#: bookwyrm/templates/book/book.html:223 +#: bookwyrm/templates/book/book.html:228 msgid "Your comments" msgstr "你的评论" -#: bookwyrm/templates/book/book.html:229 +#: bookwyrm/templates/book/book.html:234 msgid "Your quotes" msgstr "你的引用" -#: bookwyrm/templates/book/book.html:265 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "主题" -#: bookwyrm/templates/book/book.html:277 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "地点" -#: bookwyrm/templates/book/book.html:288 bookwyrm/templates/layout.html:66 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:73 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "列表" -#: bookwyrm/templates/book/book.html:299 +#: bookwyrm/templates/book/book.html:304 msgid "Add to list" msgstr "添加到列表" -#: bookwyrm/templates/book/book.html:309 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -649,9 +649,9 @@ msgstr "删除这些阅读日期" #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/layout.html:70 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -675,7 +675,7 @@ msgstr "跨站社区" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:69 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "目录" @@ -706,21 +706,30 @@ msgstr "受推荐" msgid "Recently active" msgstr "最近活跃" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +#, fuzzy +#| msgid "Your Account" +msgid "Locked account" +msgstr "你的帐号" + +#: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" msgid_plural "followers you follow" msgstr[0] "你关注的关注者" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 msgid "book on your shelves" msgid_plural "books on your shelves" msgstr[0] "你书架上的书" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "发文" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "最后活跃" @@ -756,7 +765,7 @@ msgid "Recent Books" msgstr "最近书目" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "欢迎" @@ -874,7 +883,7 @@ msgid "Direct Messages with %(username)s" msgstr "与 %(username)s 私信" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "私信" @@ -916,61 +925,49 @@ msgstr "跨站" msgid "load 0 unread status(es)" msgstr "加载 0 条未读状态" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "现在还没有任何活动!尝试从关注一个用户开始吧" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "可以关注的人" - -#: bookwyrm/templates/feed/layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "更新" -#: bookwyrm/templates/feed/layout.html:11 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "你的书目" -#: bookwyrm/templates/feed/layout.html:13 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "现在这里还没有任何书目!尝试着从搜索某本书开始吧" -#: bookwyrm/templates/feed/layout.html:24 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "To Read" msgstr "想读" -#: bookwyrm/templates/feed/layout.html:25 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Currently Reading" msgstr "在读" -#: bookwyrm/templates/feed/layout.html:26 +#: bookwyrm/templates/feed/layout.html:27 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "读过" -#: bookwyrm/templates/feed/layout.html:89 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "%(year)s 阅读目标" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "%(mutuals)s 个你也关注的关注者" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "%(shared_books)s 本在你书架上也有的书" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "可以关注的人" #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format @@ -1001,7 +998,7 @@ msgstr "你可以在开始使用 %(site_name)s 后添加书目。" #: bookwyrm/templates/get_started/books.html:17 #: bookwyrm/templates/get_started/users.html:18 #: bookwyrm/templates/get_started/users.html:19 -#: bookwyrm/templates/layout.html:42 bookwyrm/templates/layout.html:43 +#: bookwyrm/templates/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -1027,33 +1024,33 @@ msgstr "没有找到书目" msgid "Save & continue" msgstr "保存 & 继续" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, python-format msgid "Welcome to %(site_name)s!" msgstr "欢迎来到 %(site_name)s!" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "这些最初的步骤可以帮助你入门。" -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 msgid "Create your profile" msgstr "创建你的个人资料" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 msgid "Add books" msgstr "添加书目" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 msgid "Find friends" msgstr "寻找同好" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "跳过此步骤" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 msgid "Finish" msgstr "完成" @@ -1082,7 +1079,7 @@ msgid "Manually approve followers:" msgstr "手动批准关注者:" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "在推荐的用户中显示此帐号:" @@ -1163,83 +1160,83 @@ msgstr "最近的导入" msgid "No recent imports" msgstr "无最近的导入" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "导入状态" -#: bookwyrm/templates/import_status.html:10 +#: bookwyrm/templates/import_status.html:11 msgid "Back to imports" msgstr "回到导入" -#: bookwyrm/templates/import_status.html:14 +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "导入开始:" -#: bookwyrm/templates/import_status.html:19 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "导入完成:" -#: bookwyrm/templates/import_status.html:24 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "任务失败" -#: bookwyrm/templates/import_status.html:31 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "还在导入中。" -#: bookwyrm/templates/import_status.html:33 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "(按下重新加载来更新!)" -#: bookwyrm/templates/import_status.html:40 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "加载失败" -#: bookwyrm/templates/import_status.html:49 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "跳转至列表底部来选取 %(failed_count)s 个导入失败的项目。" -#: bookwyrm/templates/import_status.html:61 +#: bookwyrm/templates/import_status.html:62 #, python-format msgid "Line %(index)s: %(title)s by %(author)s" msgstr "第 %(index)s 行: %(author)s 所著的 %(title)s" -#: bookwyrm/templates/import_status.html:81 +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "全选" -#: bookwyrm/templates/import_status.html:84 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "重试项目" -#: bookwyrm/templates/import_status.html:111 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "成功导入了" -#: bookwyrm/templates/import_status.html:113 +#: bookwyrm/templates/import_status.html:114 msgid "Import Progress" msgstr "导入进度" -#: bookwyrm/templates/import_status.html:118 +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "书目" -#: bookwyrm/templates/import_status.html:121 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: bookwyrm/templates/user/shelf/shelf.html:79 #: bookwyrm/templates/user/shelf/shelf.html:99 msgid "Title" msgstr "标题" -#: bookwyrm/templates/import_status.html:124 +#: bookwyrm/templates/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "作者" -#: bookwyrm/templates/import_status.html:147 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "已导入" @@ -1269,27 +1266,27 @@ msgstr "\"%(query)s\" 的搜索结果" msgid "Matching Books" msgstr "匹配的书目" -#: bookwyrm/templates/layout.html:38 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "搜索书目或用户" -#: bookwyrm/templates/layout.html:52 bookwyrm/templates/layout.html:53 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "主导航菜单" -#: bookwyrm/templates/layout.html:63 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "动态" -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:94 msgid "Your Books" msgstr "你的书目" -#: bookwyrm/templates/layout.html:102 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "设置" -#: bookwyrm/templates/layout.html:111 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1297,61 +1294,61 @@ msgstr "设置" msgid "Invites" msgstr "邀请" -#: bookwyrm/templates/layout.html:118 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "管理员" -#: bookwyrm/templates/layout.html:125 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "登出" -#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "通知" -#: bookwyrm/templates/layout.html:156 bookwyrm/templates/layout.html:160 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "用户名:" -#: bookwyrm/templates/layout.html:161 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "密码" -#: bookwyrm/templates/layout.html:162 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "忘记了密码?" -#: bookwyrm/templates/layout.html:165 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "登录" -#: bookwyrm/templates/layout.html:173 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "加入" -#: bookwyrm/templates/layout.html:211 +#: bookwyrm/templates/layout.html:213 msgid "About this instance" msgstr "关于本实例" -#: bookwyrm/templates/layout.html:215 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "联系站点管理员" -#: bookwyrm/templates/layout.html:219 +#: bookwyrm/templates/layout.html:221 msgid "Documentation" msgstr "文档:" -#: bookwyrm/templates/layout.html:226 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "在 %(support_title)s 上支持 %(site_name)s" -#: bookwyrm/templates/layout.html:230 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm 是开源软件。你可以在 GitHub 贡献或报告问题。" @@ -1786,12 +1783,18 @@ msgstr "编辑个人资料" msgid "Show set reading goal prompt in feed:" msgstr "在消息流中显示设置阅读目标的提示:" -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +#, fuzzy +#| msgid "Post privacy" +msgid "Default post privacy:" +msgstr "发文隐私" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "你的帐号会显示在 目录 中,并可能受其它 BookWyrm 用户推荐。" -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "偏好的时区:" @@ -1823,22 +1826,22 @@ msgid "Want to Read \"%(book_title)s\"" msgstr "想要阅读 \"%(book_title)s\"" #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "评价了" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "写了书评给" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "评论了" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "引用了" @@ -1864,7 +1867,7 @@ msgstr "搜索类型" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:79 +#: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "书目" @@ -2069,7 +2072,7 @@ msgid "Details" msgstr "详细" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:61 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "活动" @@ -2331,7 +2334,7 @@ msgstr "注册关闭文字:" msgid "Posted by %(username)s" msgstr "由 %(username)s 发布" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "没有封面" @@ -2419,7 +2422,7 @@ msgstr "加入剧透警告" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "私密" @@ -2576,13 +2579,13 @@ msgstr "往后" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "公开" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "不公开" @@ -2594,7 +2597,7 @@ msgstr "仅关注者" msgid "Post privacy" msgstr "发文隐私" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2681,17 +2684,17 @@ msgstr "开始 \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" msgstr "想要阅读 \"%(book_title)s\"" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "显示更多" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "显示更少" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "在新窗口中打开图像" @@ -2714,7 +2717,7 @@ msgstr "喜欢状态" msgid "boosted" msgstr "转发了" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, python-format msgid "replied to %(username)s's status" msgstr "回复了 %(username)s状态" @@ -2734,6 +2737,25 @@ msgstr "删除并重新起草" msgid "Send direct message" msgstr "发送私信" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "%(mutuals)s 个你也关注的关注者" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "%(shared_books)s 本在你书架上也有的书" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +#, fuzzy +#| msgid "followed you" +msgid "Follows you" +msgstr "关注了你" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "切换到此版本" @@ -2750,11 +2772,11 @@ msgstr "降序排序" msgid "User Profile" msgstr "用户个人资料" -#: bookwyrm/templates/user/layout.html:42 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "关注请求" -#: bookwyrm/templates/user/layout.html:67 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "阅读目标" @@ -2860,28 +2882,35 @@ msgstr "RSS 流" msgid "No activities yet!" msgstr "还没有活动!" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "在 %(date)s 加入" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "%(counter)s 个关注者" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "关注着 %(counter)s 人" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "%(mutuals_display)s 个你也关注的关注者" +#: bookwyrm/templates/user/user_preview.html:38 +#, fuzzy +#| msgid "follower you follow" +#| msgid_plural "followers you follow" +msgid "No followers you follow" +msgstr "你关注的关注者" + #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" msgstr "回到用户" diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index e11f024b7..b7736822f 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-30 10:36+0000\n" +"POT-Creation-Date: 2021-08-04 20:40+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -18,101 +18,103 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: bookwyrm/forms.py:224 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "已經存在使用該郵箱的使用者。" -#: bookwyrm/forms.py:238 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "一天" -#: bookwyrm/forms.py:239 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "一週" -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "一個月" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "永不失效" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d 次使用" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "不受限" -#: bookwyrm/forms.py:299 +#: bookwyrm/forms.py:307 msgid "List Order" msgstr "列表順序" -#: bookwyrm/forms.py:300 +#: bookwyrm/forms.py:308 msgid "Book Title" msgstr "書名" -#: bookwyrm/forms.py:301 bookwyrm/templates/snippets/create_status_form.html:34 +#: bookwyrm/forms.py:309 bookwyrm/templates/snippets/create_status_form.html:34 #: 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:107 +#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "排序方式" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:315 msgid "Ascending" msgstr "升序" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:316 msgid "Descending" msgstr "降序" -#: bookwyrm/models/fields.py:25 +#: bookwyrm/models/fields.py:27 #, python-format msgid "%(value)s is not a valid remote_id" msgstr "%(value)s 不是有效的 remote_id" -#: bookwyrm/models/fields.py:34 bookwyrm/models/fields.py:43 +#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45 #, python-format msgid "%(value)s is not a valid username" msgstr "%(value)s 不是有效的使用者名稱" -#: bookwyrm/models/fields.py:166 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:159 msgid "username" msgstr "使用者名稱" -#: bookwyrm/models/fields.py:171 +#: bookwyrm/models/fields.py:179 msgid "A user with that username already exists." msgstr "已經存在使用該名稱的使用者。" -#: bookwyrm/settings.py:156 +#: bookwyrm/settings.py:166 msgid "English" msgstr "English(英語)" -#: bookwyrm/settings.py:157 +#: bookwyrm/settings.py:167 msgid "German" msgstr "Deutsch(德語)" -#: bookwyrm/settings.py:158 +#: bookwyrm/settings.py:168 msgid "Spanish" msgstr "Español(西班牙語)" -#: bookwyrm/settings.py:159 +#: bookwyrm/settings.py:169 msgid "French" msgstr "Français(法語)" -#: bookwyrm/settings.py:160 +#: bookwyrm/settings.py:170 msgid "Simplified Chinese" msgstr "簡體中文" -#: bookwyrm/settings.py:161 -msgid "Tranditional Chinese" +#: bookwyrm/settings.py:171 +#, fuzzy +#| msgid "Tranditional Chinese" +msgid "Traditional Chinese" msgstr "繁體中文" #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 @@ -140,34 +142,44 @@ msgstr "某些東西出錯了!抱歉。" msgid "Edit Author" msgstr "編輯作者" -#: bookwyrm/templates/author/author.html:32 -#: bookwyrm/templates/author/edit_author.html:38 +#: bookwyrm/templates/author/author.html:34 +#: bookwyrm/templates/author/edit_author.html:41 msgid "Aliases:" msgstr "別名:" -#: bookwyrm/templates/author/author.html:38 +#: bookwyrm/templates/author/author.html:45 msgid "Born:" msgstr "出生:" -#: bookwyrm/templates/author/author.html:44 +#: bookwyrm/templates/author/author.html:52 msgid "Died:" msgstr "逝世:" -#: bookwyrm/templates/author/author.html:51 +#: bookwyrm/templates/author/author.html:61 msgid "Wikipedia" msgstr "維基百科" -#: bookwyrm/templates/author/author.html:55 -#: bookwyrm/templates/book/book.html:78 +#: bookwyrm/templates/author/author.html:69 +#: bookwyrm/templates/book/book.html:95 msgid "View on OpenLibrary" msgstr "在 OpenLibrary 檢視" -#: bookwyrm/templates/author/author.html:60 -#: bookwyrm/templates/book/book.html:81 +#: bookwyrm/templates/author/author.html:77 +#: bookwyrm/templates/book/book.html:98 msgid "View on Inventaire" msgstr "在 Inventaire 檢視" -#: bookwyrm/templates/author/author.html:74 +#: bookwyrm/templates/author/author.html:85 +#, fuzzy +#| msgid "View on OpenLibrary" +msgid "View on LibraryThing" +msgstr "在 OpenLibrary 檢視" + +#: bookwyrm/templates/author/author.html:93 +msgid "View on Goodreads" +msgstr "" + +#: bookwyrm/templates/author/author.html:108 #, python-format msgid "Books by %(name)s" msgstr "%(name)s 所著的書" @@ -177,212 +189,212 @@ msgid "Edit Author:" msgstr "編輯作者:" #: bookwyrm/templates/author/edit_author.html:13 -#: bookwyrm/templates/book/edit_book.html:18 +#: bookwyrm/templates/book/edit_book.html:19 msgid "Added:" msgstr "新增了:" #: bookwyrm/templates/author/edit_author.html:14 -#: bookwyrm/templates/book/edit_book.html:19 +#: bookwyrm/templates/book/edit_book.html:24 msgid "Updated:" msgstr "更新了:" #: bookwyrm/templates/author/edit_author.html:15 -#: bookwyrm/templates/book/edit_book.html:20 +#: bookwyrm/templates/book/edit_book.html:30 msgid "Last edited by:" msgstr "最後編輯者:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:90 +#: bookwyrm/templates/book/edit_book.html:117 msgid "Metadata" msgstr "元資料" -#: bookwyrm/templates/author/edit_author.html:32 +#: bookwyrm/templates/author/edit_author.html:33 #: bookwyrm/templates/lists/form.html:8 #: bookwyrm/templates/user/shelf/create_shelf_form.html:13 #: bookwyrm/templates/user/shelf/edit_shelf_form.html:14 msgid "Name:" msgstr "名稱:" -#: bookwyrm/templates/author/edit_author.html:40 -#: bookwyrm/templates/book/edit_book.html:132 -#: bookwyrm/templates/book/edit_book.html:141 -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/author/edit_author.html:43 +#: bookwyrm/templates/book/edit_book.html:162 +#: bookwyrm/templates/book/edit_book.html:171 +#: bookwyrm/templates/book/edit_book.html:214 msgid "Separate multiple values with commas." msgstr "請用逗號(,)分隔多個值。" -#: bookwyrm/templates/author/edit_author.html:46 +#: bookwyrm/templates/author/edit_author.html:50 msgid "Bio:" msgstr "簡介:" -#: bookwyrm/templates/author/edit_author.html:51 +#: bookwyrm/templates/author/edit_author.html:57 msgid "Wikipedia link:" msgstr "維基百科連結:" -#: bookwyrm/templates/author/edit_author.html:57 +#: bookwyrm/templates/author/edit_author.html:63 msgid "Birth date:" msgstr "出生日期:" -#: bookwyrm/templates/author/edit_author.html:65 +#: bookwyrm/templates/author/edit_author.html:71 msgid "Death date:" msgstr "死亡日期:" -#: bookwyrm/templates/author/edit_author.html:73 +#: bookwyrm/templates/author/edit_author.html:79 msgid "Author Identifiers" msgstr "作者標識號:" -#: bookwyrm/templates/author/edit_author.html:74 +#: bookwyrm/templates/author/edit_author.html:81 msgid "Openlibrary key:" msgstr "Openlibrary key:" -#: bookwyrm/templates/author/edit_author.html:79 -#: bookwyrm/templates/book/edit_book.html:243 +#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/book/edit_book.html:293 msgid "Inventaire ID:" msgstr "Inventaire ID:" -#: bookwyrm/templates/author/edit_author.html:84 +#: bookwyrm/templates/author/edit_author.html:97 msgid "Librarything key:" msgstr "Librarything key:" -#: bookwyrm/templates/author/edit_author.html:89 +#: bookwyrm/templates/author/edit_author.html:105 msgid "Goodreads key:" msgstr "Goodreads key:" -#: bookwyrm/templates/author/edit_author.html:98 -#: bookwyrm/templates/book/book.html:124 -#: bookwyrm/templates/book/edit_book.html:263 +#: bookwyrm/templates/author/edit_author.html:116 +#: bookwyrm/templates/book/book.html:141 +#: bookwyrm/templates/book/edit_book.html:321 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/lists/form.html:42 -#: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/preferences/edit_user.html:78 #: 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 -#: bookwyrm/templates/snippets/readthrough.html:77 +#: bookwyrm/templates/settings/site.html:101 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "儲存" -#: bookwyrm/templates/author/edit_author.html:99 -#: bookwyrm/templates/book/book.html:125 bookwyrm/templates/book/book.html:174 +#: bookwyrm/templates/author/edit_author.html:117 +#: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:264 +#: bookwyrm/templates/book/edit_book.html:322 +#: bookwyrm/templates/book/readthrough.html:78 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:78 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:37 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 msgid "Cancel" msgstr "取消" -#: bookwyrm/templates/book/book.html:31 +#: bookwyrm/templates/book/book.html:48 #: bookwyrm/templates/discover/large-book.html:25 #: bookwyrm/templates/discover/small-book.html:19 msgid "by" msgstr "作者" -#: bookwyrm/templates/book/book.html:39 bookwyrm/templates/book/book.html:40 +#: bookwyrm/templates/book/book.html:56 bookwyrm/templates/book/book.html:57 msgid "Edit Book" msgstr "編輯書目" -#: bookwyrm/templates/book/book.html:57 +#: bookwyrm/templates/book/book.html:74 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "新增封面" -#: bookwyrm/templates/book/book.html:61 +#: bookwyrm/templates/book/book.html:78 msgid "Failed to load cover" msgstr "載入封面失敗" -#: bookwyrm/templates/book/book.html:101 +#: bookwyrm/templates/book/book.html:118 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s 則書評)" -#: bookwyrm/templates/book/book.html:113 +#: bookwyrm/templates/book/book.html:130 msgid "Add Description" msgstr "新增描述" -#: bookwyrm/templates/book/book.html:120 -#: bookwyrm/templates/book/edit_book.html:108 +#: bookwyrm/templates/book/book.html:137 +#: bookwyrm/templates/book/edit_book.html:136 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "描述:" -#: bookwyrm/templates/book/book.html:134 +#: bookwyrm/templates/book/book.html:151 #, python-format msgid "%(count)s editions" msgstr "%(count)s 個版本" -#: bookwyrm/templates/book/book.html:142 +#: bookwyrm/templates/book/book.html:159 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "此版本在你的 %(shelf_name)s 書架上。" -#: bookwyrm/templates/book/book.html:148 +#: bookwyrm/templates/book/book.html:165 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "本書的 另一個版本 在你的 %(shelf_name)s 書架上。" -#: bookwyrm/templates/book/book.html:159 +#: bookwyrm/templates/book/book.html:176 msgid "Your reading activity" msgstr "你的閱讀活動" -#: bookwyrm/templates/book/book.html:162 +#: bookwyrm/templates/book/book.html:179 msgid "Add read dates" msgstr "新增閱讀日期" -#: bookwyrm/templates/book/book.html:171 +#: bookwyrm/templates/book/book.html:188 msgid "Create" msgstr "建立" -#: bookwyrm/templates/book/book.html:181 +#: bookwyrm/templates/book/book.html:198 msgid "You don't have any reading activity for this book." msgstr "你還未閱讀這本書。" -#: bookwyrm/templates/book/book.html:200 +#: bookwyrm/templates/book/book.html:217 msgid "Reviews" msgstr "書評" -#: bookwyrm/templates/book/book.html:205 +#: bookwyrm/templates/book/book.html:222 msgid "Your reviews" msgstr "你的書評" -#: bookwyrm/templates/book/book.html:211 +#: bookwyrm/templates/book/book.html:228 msgid "Your comments" msgstr "你的評論" -#: bookwyrm/templates/book/book.html:217 +#: bookwyrm/templates/book/book.html:234 msgid "Your quotes" msgstr "你的引用" -#: bookwyrm/templates/book/book.html:253 +#: bookwyrm/templates/book/book.html:270 msgid "Subjects" msgstr "主題" -#: bookwyrm/templates/book/book.html:265 +#: bookwyrm/templates/book/book.html:282 msgid "Places" msgstr "地點" -#: bookwyrm/templates/book/book.html:276 bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/book/book.html:293 bookwyrm/templates/layout.html:68 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search/layout.html:25 #: bookwyrm/templates/search/layout.html:50 -#: bookwyrm/templates/user/layout.html:68 +#: bookwyrm/templates/user/layout.html:75 msgid "Lists" msgstr "列表" -#: bookwyrm/templates/book/book.html:287 +#: bookwyrm/templates/book/book.html:304 msgid "Add to list" msgstr "新增到列表" -#: bookwyrm/templates/book/book.html:297 +#: bookwyrm/templates/book/book.html:314 #: bookwyrm/templates/book/cover_modal.html:31 #: bookwyrm/templates/lists/list.html:179 msgid "Add" @@ -393,22 +405,22 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:301 msgid "OCLC Number:" msgstr "OCLC 號:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:253 +#: bookwyrm/templates/book/edit_book.html:309 msgid "ASIN:" msgstr "ASIN:" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:192 +#: bookwyrm/templates/book/edit_book.html:229 msgid "Upload cover:" msgstr "上載封面:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:198 +#: bookwyrm/templates/book/edit_book.html:235 msgid "Load cover from url:" msgstr "從網址載入封面:" @@ -423,127 +435,134 @@ msgstr "編輯 \"%(book_title)s\"" msgid "Add Book" msgstr "新增書目" -#: bookwyrm/templates/book/edit_book.html:40 +#: bookwyrm/templates/book/edit_book.html:54 msgid "Confirm Book Info" msgstr "確認書目資料" -#: bookwyrm/templates/book/edit_book.html:47 +#: bookwyrm/templates/book/edit_book.html:62 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "\"%(name)s\" 是已存在的作者嗎?" -#: bookwyrm/templates/book/edit_book.html:52 +#: bookwyrm/templates/book/edit_book.html:71 #, python-format msgid "Author of %(book_title)s" msgstr "%(book_title)s 的作者" -#: bookwyrm/templates/book/edit_book.html:55 +#: bookwyrm/templates/book/edit_book.html:75 msgid "This is a new author" msgstr "這是一位新的作者" -#: bookwyrm/templates/book/edit_book.html:61 +#: bookwyrm/templates/book/edit_book.html:82 #, python-format msgid "Creating a new author: %(name)s" msgstr "正在建立新的作者: %(name)s" -#: bookwyrm/templates/book/edit_book.html:67 +#: bookwyrm/templates/book/edit_book.html:89 msgid "Is this an edition of an existing work?" msgstr "這是已存在的作品的另一個版本嗎?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:97 msgid "This is a new work" msgstr "這是一個新的作品。" -#: bookwyrm/templates/book/edit_book.html:77 +#: bookwyrm/templates/book/edit_book.html:104 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "確認" -#: bookwyrm/templates/book/edit_book.html:79 +#: bookwyrm/templates/book/edit_book.html:106 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "返回" -#: bookwyrm/templates/book/edit_book.html:93 +#: bookwyrm/templates/book/edit_book.html:120 msgid "Title:" msgstr "標題:" -#: bookwyrm/templates/book/edit_book.html:101 +#: bookwyrm/templates/book/edit_book.html:128 msgid "Subtitle:" msgstr "副標題:" -#: bookwyrm/templates/book/edit_book.html:114 +#: bookwyrm/templates/book/edit_book.html:144 msgid "Series:" msgstr "系列:" -#: bookwyrm/templates/book/edit_book.html:122 +#: bookwyrm/templates/book/edit_book.html:152 msgid "Series number:" msgstr "系列編號:" -#: bookwyrm/templates/book/edit_book.html:130 +#: bookwyrm/templates/book/edit_book.html:160 msgid "Languages:" msgstr "語言:" -#: bookwyrm/templates/book/edit_book.html:139 +#: bookwyrm/templates/book/edit_book.html:169 msgid "Publisher:" msgstr "出版社:" -#: bookwyrm/templates/book/edit_book.html:148 +#: bookwyrm/templates/book/edit_book.html:178 msgid "First published date:" msgstr "初版時間:" -#: bookwyrm/templates/book/edit_book.html:156 +#: bookwyrm/templates/book/edit_book.html:186 msgid "Published date:" msgstr "出版時間:" -#: bookwyrm/templates/book/edit_book.html:165 +#: bookwyrm/templates/book/edit_book.html:195 msgid "Authors" msgstr "作者" -#: bookwyrm/templates/book/edit_book.html:171 -#, python-format -msgid "Remove %(name)s" -msgstr "移除 %(name)s" +#: bookwyrm/templates/book/edit_book.html:202 +#, fuzzy, python-format +#| msgid "Remove from %(name)s" +msgid "Remove %(name)s" +msgstr "從 %(name)s 移除" -#: bookwyrm/templates/book/edit_book.html:176 +#: bookwyrm/templates/book/edit_book.html:205 +#, fuzzy, python-format +#| msgid "Remove from %(name)s" +msgid "Author page for %(name)s" +msgstr "從 %(name)s 移除" + +#: bookwyrm/templates/book/edit_book.html:212 msgid "Add Authors:" msgstr "新增作者:" -#: bookwyrm/templates/book/edit_book.html:177 +#: bookwyrm/templates/book/edit_book.html:213 msgid "John Doe, Jane Smith" msgstr "John Doe, Jane Smith" -#: bookwyrm/templates/book/edit_book.html:183 +#: bookwyrm/templates/book/edit_book.html:220 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "封面" -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:248 msgid "Physical Properties" msgstr "實體性質" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:250 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "格式:" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:258 msgid "Pages:" msgstr "頁數:" -#: bookwyrm/templates/book/edit_book.html:227 +#: bookwyrm/templates/book/edit_book.html:267 msgid "Book Identifiers" msgstr "書目標識號" -#: bookwyrm/templates/book/edit_book.html:228 +#: bookwyrm/templates/book/edit_book.html:269 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:233 +#: bookwyrm/templates/book/edit_book.html:277 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:238 +#: bookwyrm/templates/book/edit_book.html:285 msgid "Openlibrary ID:" msgstr "Openlibrary ID:" @@ -605,11 +624,40 @@ msgstr "由 %(publisher)s 出版。" msgid "rated it" msgstr "評價了" +#: bookwyrm/templates/book/readthrough.html:8 +msgid "Progress Updates:" +msgstr "進度更新:" + +#: bookwyrm/templates/book/readthrough.html:14 +msgid "finished" +msgstr "已完成" + +#: bookwyrm/templates/book/readthrough.html:25 +msgid "Show all updates" +msgstr "顯示所有更新" + +#: bookwyrm/templates/book/readthrough.html:41 +msgid "Delete this progress update" +msgstr "刪除此進度更新" + +#: bookwyrm/templates/book/readthrough.html:52 +msgid "started" +msgstr "已開始" + +#: bookwyrm/templates/book/readthrough.html:59 +#: bookwyrm/templates/book/readthrough.html:73 +msgid "Edit read dates" +msgstr "編輯閱讀日期" + +#: bookwyrm/templates/book/readthrough.html:63 +msgid "Delete these read dates" +msgstr "刪除這些閱讀日期" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:69 -#: bookwyrm/templates/get_started/layout.html:19 -#: bookwyrm/templates/get_started/layout.html:52 +#: bookwyrm/templates/feed/layout.html:71 +#: bookwyrm/templates/get_started/layout.html:20 +#: bookwyrm/templates/get_started/layout.html:53 #: bookwyrm/templates/search/book.html:32 #: bookwyrm/templates/snippets/announcement.html:18 msgid "Close" @@ -633,7 +681,7 @@ msgstr "跨站社群" #: bookwyrm/templates/directory/directory.html:4 #: bookwyrm/templates/directory/directory.html:9 -#: bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/layout.html:71 msgid "Directory" msgstr "目錄" @@ -664,21 +712,30 @@ msgstr "受推薦" msgid "Recently active" msgstr "最近活躍" -#: bookwyrm/templates/directory/user_card.html:33 +#: bookwyrm/templates/directory/user_card.html:17 +#: bookwyrm/templates/directory/user_card.html:18 +#: bookwyrm/templates/user/user_preview.html:16 +#: bookwyrm/templates/user/user_preview.html:17 +#, fuzzy +#| msgid "Your Account" +msgid "Locked account" +msgstr "你的帳號" + +#: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" msgid_plural "followers you follow" msgstr[0] "你關注的關注者" -#: bookwyrm/templates/directory/user_card.html:40 +#: bookwyrm/templates/directory/user_card.html:47 msgid "book on your shelves" msgid_plural "books on your shelves" msgstr[0] "你書架上的書" -#: bookwyrm/templates/directory/user_card.html:48 +#: bookwyrm/templates/directory/user_card.html:55 msgid "posts" msgstr "發文" -#: bookwyrm/templates/directory/user_card.html:54 +#: bookwyrm/templates/directory/user_card.html:61 msgid "last active" msgstr "最後活躍" @@ -714,7 +771,7 @@ msgid "Recent Books" msgstr "最近書目" #: bookwyrm/templates/discover/landing_layout.html:5 -#: bookwyrm/templates/get_started/layout.html:4 +#: bookwyrm/templates/get_started/layout.html:5 msgid "Welcome" msgstr "歡迎" @@ -832,7 +889,7 @@ msgid "Direct Messages with %(username)s" msgstr "與 %(username)s 私信" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:99 msgid "Direct Messages" msgstr "私信" @@ -874,61 +931,49 @@ msgstr "跨站" msgid "load 0 unread status(es)" msgstr "載入 0 條未讀狀態" -#: bookwyrm/templates/feed/feed.html:47 +#: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" msgstr "現在還沒有任何活動!嘗試著從關注一個使用者開始吧" -#: bookwyrm/templates/feed/feed.html:55 -#: bookwyrm/templates/get_started/users.html:6 -msgid "Who to follow" -msgstr "可以關注的人" - -#: bookwyrm/templates/feed/feed_layout.html:4 +#: bookwyrm/templates/feed/layout.html:5 msgid "Updates" msgstr "更新" -#: bookwyrm/templates/feed/feed_layout.html:10 +#: bookwyrm/templates/feed/layout.html:12 #: bookwyrm/templates/user/shelf/books_header.html:3 msgid "Your books" msgstr "你的書目" -#: bookwyrm/templates/feed/feed_layout.html:12 +#: bookwyrm/templates/feed/layout.html:14 msgid "There are no books here right now! Try searching for a book to get started" msgstr "現在這裡還沒有任何書目!嘗試著從搜尋某本書開始吧" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/layout.html:25 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "To Read" msgstr "想讀" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/layout.html:26 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Currently Reading" msgstr "在讀" -#: bookwyrm/templates/feed/feed_layout.html:25 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:13 +#: bookwyrm/templates/feed/layout.html:27 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 #: bookwyrm/templates/user/shelf/shelf.html:29 msgid "Read" msgstr "讀過" -#: bookwyrm/templates/feed/feed_layout.html:87 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/layout.html:90 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" msgstr "%(year)s 閱讀目標" -#: bookwyrm/templates/feed/suggested_users.html:16 -#, python-format -msgid "%(mutuals)s follower you follow" -msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "%(mutuals)s 個你也關注的關注者" - -#: bookwyrm/templates/feed/suggested_users.html:19 -#, python-format -msgid "%(shared_books)s book on your shelves" -msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "%(shared_books)s 本在你書架上也有的書" +#: bookwyrm/templates/feed/suggested_users.html:3 +#: bookwyrm/templates/get_started/users.html:6 +msgid "Who to follow" +msgstr "可以關注的人" #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format @@ -959,7 +1004,7 @@ msgstr "你可以在開始使用 %(site_name)s 後新增書目。" #: bookwyrm/templates/get_started/books.html:17 #: 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/layout.html:44 bookwyrm/templates/layout.html:45 #: bookwyrm/templates/lists/list.html:139 #: bookwyrm/templates/search/layout.html:4 #: bookwyrm/templates/search/layout.html:9 @@ -985,33 +1030,33 @@ msgstr "沒有找到書目" msgid "Save & continue" msgstr "儲存 & 繼續" -#: bookwyrm/templates/get_started/layout.html:14 +#: bookwyrm/templates/get_started/layout.html:15 #, python-format msgid "Welcome to %(site_name)s!" msgstr "歡迎來到 %(site_name)s!" -#: bookwyrm/templates/get_started/layout.html:16 +#: bookwyrm/templates/get_started/layout.html:17 msgid "These are some first steps to get you started." msgstr "這些最初的步驟可以幫助你入門。" -#: bookwyrm/templates/get_started/layout.html:30 +#: bookwyrm/templates/get_started/layout.html:31 #: bookwyrm/templates/get_started/profile.html:6 msgid "Create your profile" msgstr "建立你的使用者資料" -#: bookwyrm/templates/get_started/layout.html:34 +#: bookwyrm/templates/get_started/layout.html:35 msgid "Add books" msgstr "新增書目" -#: bookwyrm/templates/get_started/layout.html:38 +#: bookwyrm/templates/get_started/layout.html:39 msgid "Find friends" msgstr "尋找同好" -#: bookwyrm/templates/get_started/layout.html:44 +#: bookwyrm/templates/get_started/layout.html:45 msgid "Skip this step" msgstr "跳過此步驟" -#: bookwyrm/templates/get_started/layout.html:48 +#: bookwyrm/templates/get_started/layout.html:49 msgid "Finish" msgstr "完成" @@ -1040,7 +1085,7 @@ msgid "Manually approve followers:" msgstr "手動批准關注者:" #: bookwyrm/templates/get_started/profile.html:48 -#: bookwyrm/templates/preferences/edit_user.html:58 +#: bookwyrm/templates/preferences/edit_user.html:66 msgid "Show this account in suggested users:" msgstr "在推薦的使用者中顯示此帳號:" @@ -1121,70 +1166,87 @@ msgstr "最近的匯入" msgid "No recent imports" msgstr "無最近的匯入" -#: bookwyrm/templates/import_status.html:5 -#: bookwyrm/templates/import_status.html:9 +#: bookwyrm/templates/import_status.html:6 +#: bookwyrm/templates/import_status.html:10 msgid "Import Status" msgstr "匯入狀態" -#: bookwyrm/templates/import_status.html:12 +#: bookwyrm/templates/import_status.html:11 +#, fuzzy +#| msgid "Back to reports" +msgid "Back to imports" +msgstr "回到舉報" + +#: bookwyrm/templates/import_status.html:15 msgid "Import started:" msgstr "匯入開始:" -#: bookwyrm/templates/import_status.html:16 +#: bookwyrm/templates/import_status.html:20 msgid "Import completed:" msgstr "匯入完成:" -#: bookwyrm/templates/import_status.html:19 +#: bookwyrm/templates/import_status.html:25 msgid "TASK FAILED" msgstr "任務失敗" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:32 msgid "Import still in progress." msgstr "還在匯入中。" -#: bookwyrm/templates/import_status.html:27 +#: bookwyrm/templates/import_status.html:34 msgid "(Hit reload to update!)" msgstr "(按下重新載入來更新!)" -#: bookwyrm/templates/import_status.html:34 +#: bookwyrm/templates/import_status.html:41 msgid "Failed to load" msgstr "載入失敗" -#: bookwyrm/templates/import_status.html:43 +#: bookwyrm/templates/import_status.html:50 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." msgstr "跳轉至列表底部來選取 %(failed_count)s 個匯入失敗的項目。" -#: bookwyrm/templates/import_status.html:78 +#: bookwyrm/templates/import_status.html:62 +#, python-format +msgid "Line %(index)s: %(title)s by %(author)s" +msgstr "" + +#: bookwyrm/templates/import_status.html:82 msgid "Select all" msgstr "全選" -#: bookwyrm/templates/import_status.html:81 +#: bookwyrm/templates/import_status.html:85 msgid "Retry items" msgstr "重試項目" -#: bookwyrm/templates/import_status.html:107 +#: bookwyrm/templates/import_status.html:112 msgid "Successfully imported" msgstr "成功匯入了" -#: bookwyrm/templates/import_status.html:111 +#: bookwyrm/templates/import_status.html:114 +#, fuzzy +#| msgid "Import still in progress." +msgid "Import Progress" +msgstr "還在匯入中。" + +#: bookwyrm/templates/import_status.html:119 msgid "Book" msgstr "書目" -#: bookwyrm/templates/import_status.html:114 +#: bookwyrm/templates/import_status.html:122 #: bookwyrm/templates/snippets/create_status_form.html:13 #: 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/import_status.html:125 #: bookwyrm/templates/user/shelf/shelf.html:80 #: bookwyrm/templates/user/shelf/shelf.html:102 msgid "Author" msgstr "作者" -#: bookwyrm/templates/import_status.html:140 +#: bookwyrm/templates/import_status.html:148 msgid "Imported" msgstr "已匯入" @@ -1214,27 +1276,27 @@ msgstr "\"%(query)s\" 的搜尋結果" msgid "Matching Books" msgstr "匹配的書目" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:40 msgid "Search for a book or user" msgstr "搜尋書目或使用者" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55 msgid "Main navigation menu" msgstr "主導航選單" -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:65 msgid "Feed" msgstr "動態" -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:94 msgid "Your Books" msgstr "你的書目" -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:104 msgid "Settings" msgstr "設定" -#: bookwyrm/templates/layout.html:106 +#: bookwyrm/templates/layout.html:113 #: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1242,61 +1304,61 @@ msgstr "設定" msgid "Invites" msgstr "邀請" -#: bookwyrm/templates/layout.html:113 +#: bookwyrm/templates/layout.html:120 msgid "Admin" msgstr "管理員" -#: bookwyrm/templates/layout.html:120 +#: bookwyrm/templates/layout.html:127 msgid "Log out" msgstr "登出" -#: bookwyrm/templates/layout.html:128 bookwyrm/templates/layout.html:129 +#: bookwyrm/templates/layout.html:135 bookwyrm/templates/layout.html:136 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:11 msgid "Notifications" msgstr "通知" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "使用者名稱:" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:163 msgid "password" msgstr "密碼" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "忘記了密碼?" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "登入" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:175 msgid "Join" msgstr "加入" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:213 msgid "About this instance" msgstr "關於本實例" -#: bookwyrm/templates/layout.html:210 +#: bookwyrm/templates/layout.html:217 msgid "Contact site admin" msgstr "聯絡網站管理員" -#: bookwyrm/templates/layout.html:214 +#: bookwyrm/templates/layout.html:221 msgid "Documentation" msgstr "文件:" -#: bookwyrm/templates/layout.html:221 +#: bookwyrm/templates/layout.html:228 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "在 %(support_title)s 上支援 %(site_name)s" -#: bookwyrm/templates/layout.html:225 +#: bookwyrm/templates/layout.html:232 msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm 是開源軟體。你可以在 GitHub 貢獻或報告問題。" @@ -1674,6 +1736,7 @@ msgstr "你什麼也沒錯過!" #: bookwyrm/templates/password_reset.html:23 #: bookwyrm/templates/preferences/change_password.html:18 +#: bookwyrm/templates/preferences/delete_user.html:20 msgid "Confirm password:" msgstr "確認密碼:" @@ -1687,7 +1750,7 @@ msgstr "重設密碼" #: bookwyrm/templates/preferences/blocks.html:4 #: bookwyrm/templates/preferences/blocks.html:7 -#: bookwyrm/templates/preferences/preferences_layout.html:26 +#: bookwyrm/templates/preferences/layout.html:30 msgid "Blocked Users" msgstr "封鎖的使用者" @@ -1698,7 +1761,7 @@ msgstr "當前沒有被封鎖的使用者。" #: bookwyrm/templates/preferences/change_password.html:4 #: bookwyrm/templates/preferences/change_password.html:7 #: bookwyrm/templates/preferences/change_password.html:21 -#: bookwyrm/templates/preferences/preferences_layout.html:19 +#: bookwyrm/templates/preferences/layout.html:19 msgid "Change Password" msgstr "更改密碼" @@ -1706,6 +1769,23 @@ msgstr "更改密碼" msgid "New password:" msgstr "新密碼:" +#: bookwyrm/templates/preferences/delete_user.html:4 +#: bookwyrm/templates/preferences/delete_user.html:7 +#: bookwyrm/templates/preferences/delete_user.html:26 +#: bookwyrm/templates/preferences/layout.html:23 +#, fuzzy +#| msgid "Create an Account" +msgid "Delete Account" +msgstr "建立帳號" + +#: bookwyrm/templates/preferences/delete_user.html:12 +msgid "Permanently delete account" +msgstr "" + +#: bookwyrm/templates/preferences/delete_user.html:14 +msgid "Deleting your account cannot be undone. The username will not be available to register in the future." +msgstr "" + #: bookwyrm/templates/preferences/edit_user.html:4 #: bookwyrm/templates/preferences/edit_user.html:7 msgid "Edit Profile" @@ -1715,44 +1795,68 @@ msgstr "編輯使用者資料" msgid "Show set reading goal prompt in feed:" msgstr "在即時動態中顯示設定的閱讀目標提示:" -#: bookwyrm/templates/preferences/edit_user.html:62 +#: bookwyrm/templates/preferences/edit_user.html:58 +#, fuzzy +#| msgid "Post privacy" +msgid "Default post privacy:" +msgstr "發文隱私" + +#: bookwyrm/templates/preferences/edit_user.html:70 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." msgstr "你的帳號會顯示在 目錄 中,並可能受其它 BookWyrm 使用者推薦。" -#: bookwyrm/templates/preferences/edit_user.html:65 +#: bookwyrm/templates/preferences/edit_user.html:73 msgid "Preferred Timezone: " msgstr "偏好時區:" -#: bookwyrm/templates/preferences/preferences_layout.html:11 +#: bookwyrm/templates/preferences/layout.html:11 msgid "Account" msgstr "帳號" -#: bookwyrm/templates/preferences/preferences_layout.html:15 +#: bookwyrm/templates/preferences/layout.html:15 msgid "Profile" msgstr "使用者資料" -#: bookwyrm/templates/preferences/preferences_layout.html:22 +#: bookwyrm/templates/preferences/layout.html:26 msgid "Relationships" msgstr "關係" +#: bookwyrm/templates/reading_progress/finish.html:5 +#, fuzzy, python-format +#| msgid "Finish \"%(book_title)s\"" +msgid "Finish \"%(book_title)s\"" +msgstr "完成 \"%(book_title)s\"" + +#: bookwyrm/templates/reading_progress/start.html:5 +#, fuzzy, python-format +#| msgid "Edit \"%(book_title)s\"" +msgid "Start \"%(book_title)s\"" +msgstr "編輯 \"%(book_title)s\"" + +#: bookwyrm/templates/reading_progress/want.html:5 +#, fuzzy, python-format +#| msgid "Want to Read \"%(book_title)s\"" +msgid "Want to Read \"%(book_title)s\"" +msgstr "想要閱讀 \"%(book_title)s\"" + #: bookwyrm/templates/rss/title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:35 +#: bookwyrm/templates/snippets/status/status_header.html:36 msgid "rated" msgstr "評價了" #: bookwyrm/templates/rss/title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:37 +#: bookwyrm/templates/snippets/status/status_header.html:38 msgid "reviewed" msgstr "寫了書評給" #: bookwyrm/templates/rss/title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:39 +#: bookwyrm/templates/snippets/status/status_header.html:40 msgid "commented on" msgstr "評論了" #: bookwyrm/templates/rss/title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:41 +#: bookwyrm/templates/snippets/status/status_header.html:42 msgid "quoted" msgstr "引用了" @@ -1778,7 +1882,7 @@ msgstr "搜尋類別" #: bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:74 +#: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "書目" @@ -1983,7 +2087,7 @@ msgid "Details" msgstr "詳細" #: bookwyrm/templates/settings/federated_server.html:39 -#: bookwyrm/templates/user/layout.html:56 +#: bookwyrm/templates/user/layout.html:63 msgid "Activity" msgstr "活動" @@ -2022,7 +2126,7 @@ msgid "Edit" msgstr "編輯" #: bookwyrm/templates/settings/federated_server.html:105 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:8 msgid "Actions" msgstr "動作" @@ -2228,15 +2332,19 @@ msgstr "管理員郵件:" msgid "Additional info:" msgstr "附加資訊:" -#: bookwyrm/templates/settings/site.html:83 -msgid "Allow registration:" +#: bookwyrm/templates/settings/site.html:85 +#, fuzzy +#| msgid "Allow registration:" +msgid "Allow registration" msgstr "允許註冊:" -#: bookwyrm/templates/settings/site.html:87 -msgid "Allow invite requests:" +#: bookwyrm/templates/settings/site.html:91 +#, fuzzy +#| msgid "Allow invite requests:" +msgid "Allow invite requests" msgstr "允許請求邀請:" -#: bookwyrm/templates/settings/site.html:91 +#: bookwyrm/templates/settings/site.html:95 msgid "Registration closed text:" msgstr "註冊關閉文字:" @@ -2245,7 +2353,7 @@ msgstr "註冊關閉文字:" msgid "Posted by %(username)s" msgstr "由 %(username)s 釋出" -#: bookwyrm/templates/snippets/book_cover.html:31 +#: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "沒有封面" @@ -2333,7 +2441,7 @@ msgstr "加入劇透警告" #: bookwyrm/templates/snippets/create_status_form.html:117 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 -#: bookwyrm/templates/snippets/privacy_select.html:19 +#: bookwyrm/templates/snippets/privacy_select.html:20 msgid "Private" msgstr "私密" @@ -2446,7 +2554,7 @@ msgstr "目標隱私:" #: bookwyrm/templates/snippets/goal_form.html:26 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:29 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 msgid "Post to feed" msgstr "發佈到即時動態" @@ -2490,13 +2598,13 @@ msgstr "往後" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 -#: bookwyrm/templates/snippets/privacy_select.html:10 +#: bookwyrm/templates/snippets/privacy_select.html:11 msgid "Public" msgstr "公開" #: bookwyrm/templates/snippets/privacy-icons.html:7 #: bookwyrm/templates/snippets/privacy-icons.html:8 -#: bookwyrm/templates/snippets/privacy_select.html:13 +#: bookwyrm/templates/snippets/privacy_select.html:14 msgid "Unlisted" msgstr "不公開" @@ -2508,7 +2616,7 @@ msgstr "僅關注者" msgid "Post privacy" msgstr "發文隱私" -#: bookwyrm/templates/snippets/privacy_select.html:16 +#: bookwyrm/templates/snippets/privacy_select.html:17 #: bookwyrm/templates/user/relationships/followers.html:6 #: bookwyrm/templates/user/relationships/layout.html:11 msgid "Followers" @@ -2522,38 +2630,9 @@ msgstr "留下評價" msgid "Rate" msgstr "評價" -#: bookwyrm/templates/snippets/readthrough.html:8 -msgid "Progress Updates:" -msgstr "進度更新:" - -#: bookwyrm/templates/snippets/readthrough.html:14 -msgid "finished" -msgstr "已完成" - -#: bookwyrm/templates/snippets/readthrough.html:25 -msgid "Show all updates" -msgstr "顯示所有更新" - -#: bookwyrm/templates/snippets/readthrough.html:41 -msgid "Delete this progress update" -msgstr "刪除此進度更新" - -#: bookwyrm/templates/snippets/readthrough.html:52 -msgid "started" -msgstr "已開始" - -#: bookwyrm/templates/snippets/readthrough.html:59 -#: bookwyrm/templates/snippets/readthrough.html:73 -msgid "Edit read dates" -msgstr "編輯閱讀日期" - -#: bookwyrm/templates/snippets/readthrough.html:63 -msgid "Delete these read dates" -msgstr "刪除這些閱讀日期" - #: bookwyrm/templates/snippets/readthrough_form.html:7 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:17 +#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "已開始閱讀" @@ -2588,7 +2667,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "完成 \"%(book_title)s\"" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:36 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 msgid "Update progress" msgstr "更新進度" @@ -2596,20 +2675,20 @@ msgstr "更新進度" msgid "More shelves" msgstr "更多書架" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:10 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 msgid "Start reading" msgstr "開始閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:15 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 msgid "Finish reading" msgstr "完成閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:18 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 #: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 msgid "Want to read" msgstr "想要閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 #, python-format msgid "Remove from %(name)s" msgstr "從 %(name)s 移除" @@ -2624,17 +2703,17 @@ msgstr "開始 \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" msgstr "想要閱讀 \"%(book_title)s\"" -#: bookwyrm/templates/snippets/status/content_status.html:71 +#: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:15 msgid "Show more" msgstr "顯示更多" -#: bookwyrm/templates/snippets/status/content_status.html:86 +#: bookwyrm/templates/snippets/status/content_status.html:87 #: bookwyrm/templates/snippets/trimmed_text.html:30 msgid "Show less" msgstr "顯示更少" -#: bookwyrm/templates/snippets/status/content_status.html:116 +#: bookwyrm/templates/snippets/status/content_status.html:117 msgid "Open image in new window" msgstr "在新視窗中開啟圖片" @@ -2657,7 +2736,7 @@ msgstr "喜歡狀態" msgid "boosted" msgstr "轉發了" -#: bookwyrm/templates/snippets/status/status_header.html:45 +#: bookwyrm/templates/snippets/status/status_header.html:46 #, python-format msgid "replied to %(username)s's status" msgstr "回覆了 %(username)s狀態" @@ -2673,10 +2752,29 @@ msgstr "刪除並重新起草" #: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 -#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:12 msgid "Send direct message" msgstr "發送私信" +#: bookwyrm/templates/snippets/suggested_users.html:16 +#, python-format +msgid "%(mutuals)s follower you follow" +msgid_plural "%(mutuals)s followers you follow" +msgstr[0] "%(mutuals)s 個你也關注的關注者" + +#: bookwyrm/templates/snippets/suggested_users.html:23 +#, python-format +msgid "%(shared_books)s book on your shelves" +msgid_plural "%(shared_books)s books on your shelves" +msgstr[0] "%(shared_books)s 本在你書架上也有的書" + +#: bookwyrm/templates/snippets/suggested_users.html:31 +#: bookwyrm/templates/user/user_preview.html:36 +#, fuzzy +#| msgid "followed you" +msgid "Follows you" +msgstr "關注了你" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "切換到此版本" @@ -2689,15 +2787,15 @@ msgstr "升序排序" msgid "Sorted descending" msgstr "降序排序" -#: bookwyrm/templates/user/layout.html:13 bookwyrm/templates/user/user.html:10 +#: bookwyrm/templates/user/layout.html:18 bookwyrm/templates/user/user.html:10 msgid "User Profile" msgstr "使用者使用者資料" -#: bookwyrm/templates/user/layout.html:37 +#: bookwyrm/templates/user/layout.html:44 msgid "Follow Requests" msgstr "關注請求" -#: bookwyrm/templates/user/layout.html:62 +#: bookwyrm/templates/user/layout.html:69 msgid "Reading Goal" msgstr "閱讀目標" @@ -2803,28 +2901,35 @@ msgstr "RSS 訂閱" msgid "No activities yet!" msgstr "還沒有活動!" -#: bookwyrm/templates/user/user_preview.html:15 +#: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" msgstr "在 %(date)s 加入" -#: bookwyrm/templates/user/user_preview.html:19 +#: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" msgstr[0] "%(counter)s 個關注者" -#: bookwyrm/templates/user/user_preview.html:20 +#: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" msgstr "關注著 %(counter)s 人" -#: bookwyrm/templates/user/user_preview.html:26 +#: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" msgstr[0] "%(mutuals_display)s 個你也關注的關注者" +#: bookwyrm/templates/user/user_preview.html:38 +#, fuzzy +#| msgid "follower you follow" +#| msgid_plural "followers you follow" +msgid "No followers you follow" +msgstr "你關注的關注者" + #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" msgstr "回到使用者" @@ -2880,22 +2985,31 @@ msgstr "實例詳情" msgid "View instance" msgstr "檢視實例" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:5 +msgid "Permanently deleted" +msgstr "" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:17 msgid "Suspend user" msgstr "停用使用者" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:19 msgid "Un-suspend user" msgstr "取消停用使用者" -#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:28 msgid "Access level:" msgstr "訪問權限:" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:3 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 msgid "File exceeds maximum size: 10MB" msgstr "檔案超過了最大大小: 10MB" +#: bookwyrm/templatetags/utilities.py:30 +#, python-format +msgid "%(title)s: %(subtitle)s" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "不是有效的 csv 檔案" @@ -2909,3 +3023,5 @@ msgstr "沒有找到使用該郵箱的使用者。" msgid "A password reset link sent to %s" msgstr "密碼重置連結已傳送給 %s" +#~ msgid "Remove %(name)s" +#~ msgstr "移除 %(name)s" From 48fcdcbe93a6171ef249e22726ad4ae0e56ea80c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 14:12:37 -0700 Subject: [PATCH 0090/1024] Python formatting --- ...077_rename_physical_format_edition_physical_format_detail.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/migrations/0077_rename_physical_format_edition_physical_format_detail.py b/bookwyrm/migrations/0077_rename_physical_format_edition_physical_format_detail.py index 020cc49ab..fcff93523 100644 --- a/bookwyrm/migrations/0077_rename_physical_format_edition_physical_format_detail.py +++ b/bookwyrm/migrations/0077_rename_physical_format_edition_physical_format_detail.py @@ -67,9 +67,11 @@ def infer_format(app_registry, schema_editor): edition.physical_format = matches[0] edition.save() + def reverse(app_registry, schema_editor): """doesn't need to do anything""" + class Migration(migrations.Migration): dependencies = [ From 2c08be79f86f11f103d09645eebe02b8d10c6111 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 14:19:17 -0700 Subject: [PATCH 0091/1024] Merge migration --- bookwyrm/migrations/0080_merge_20210804_2114.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 bookwyrm/migrations/0080_merge_20210804_2114.py diff --git a/bookwyrm/migrations/0080_merge_20210804_2114.py b/bookwyrm/migrations/0080_merge_20210804_2114.py new file mode 100644 index 000000000..d8365eaf4 --- /dev/null +++ b/bookwyrm/migrations/0080_merge_20210804_2114.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.4 on 2021-08-04 21:14 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0077_rename_physical_format_edition_physical_format_detail"), + ("bookwyrm", "0079_merge_20210804_1746"), + ] + + operations = [] From a8d6dbd8a69b06d53c89c8707f88d411ffc60120 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 16:56:08 -0700 Subject: [PATCH 0092/1024] Adds books stream audience --- bookwyrm/activitystreams.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index a49a7ce4d..cdfebfd0d 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -173,6 +173,34 @@ class FederatedStream(ActivityStream): privacy_levels=["public"], ) +class BooksStream(ActivityStream): + """books on your shelves""" + + key = "books" + + def get_audience(self, status): + """anyone with the mentioned book on their shelves""" + # only show public statuses on the books feed, + # and only statuses that mention books + if status.privacy != "public" or not (status.mention_books.exists() or hasattr(status, "book")): + return [] + + work = status.book.parent_work if hasattr(status, "book") else status.mention_books.first().parent_work + + audience = super().get_audience(status) + if not audience: + return [] + return audience.filter( + shelfbook__book__parent_work=work + ).distinct() + + def get_statuses_for_user(self, user): + """any public status that mentions their books""" + return privacy_filter( + user, + models.Status.objects.select_subclasses().filter(, + privacy_levels=["public"], + ) streams = { "home": HomeStream(), From 5a9dbc50da23f0c1a08eb1f4d7500996d30fa3d1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 17:25:31 -0700 Subject: [PATCH 0093/1024] Adds books stream --- bookwyrm/activitystreams.py | 29 +++++++++++++++---- .../0080_alter_shelfbook_options.py | 17 +++++++++++ bookwyrm/settings.py | 2 +- bookwyrm/urls.py | 4 ++- 4 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/migrations/0080_alter_shelfbook_options.py diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index cdfebfd0d..4e464b3cb 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -173,6 +173,7 @@ class FederatedStream(ActivityStream): privacy_levels=["public"], ) + class BooksStream(ActivityStream): """books on your shelves""" @@ -182,30 +183,46 @@ class BooksStream(ActivityStream): """anyone with the mentioned book on their shelves""" # only show public statuses on the books feed, # and only statuses that mention books - if status.privacy != "public" or not (status.mention_books.exists() or hasattr(status, "book")): + if status.privacy != "public" or not ( + status.mention_books.exists() or hasattr(status, "book") + ): return [] - work = status.book.parent_work if hasattr(status, "book") else status.mention_books.first().parent_work + work = ( + status.book.parent_work + if hasattr(status, "book") + else status.mention_books.first().parent_work + ) audience = super().get_audience(status) if not audience: return [] - return audience.filter( - shelfbook__book__parent_work=work - ).distinct() + return audience.filter(shelfbook__book__parent_work=work).distinct() def get_statuses_for_user(self, user): """any public status that mentions their books""" + books = user.shelfbook_set.values_list( + "book__parent_work__id", flat=True + ).distinct() return privacy_filter( user, - models.Status.objects.select_subclasses().filter(, + models.Status.objects.select_subclasses() + .filter( + Q(comment__book__parent_work__id__in=books) + | Q(quotation__book__parent_work__id__in=books) + | Q(review__book__parent_work__id__in=books) + | Q(mention_books__parent_work__id__in=books) + ) + .distinct(), privacy_levels=["public"], ) + streams = { "home": HomeStream(), "local": LocalStream(), "federated": FederatedStream(), + "books": BooksStream(), } diff --git a/bookwyrm/migrations/0080_alter_shelfbook_options.py b/bookwyrm/migrations/0080_alter_shelfbook_options.py new file mode 100644 index 000000000..b5ee7e673 --- /dev/null +++ b/bookwyrm/migrations/0080_alter_shelfbook_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.4 on 2021-08-05 00:00 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0079_merge_20210804_1746"), + ] + + operations = [ + migrations.AlterModelOptions( + name="shelfbook", + options={"ordering": ("-shelved_date", "-created_date", "-updated_date")}, + ), + ] diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 17fcfabe5..a10f128d6 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -118,7 +118,7 @@ REDIS_ACTIVITY_PORT = env("REDIS_ACTIVITY_PORT", 6379) REDIS_ACTIVITY_PASSWORD = env("REDIS_ACTIVITY_PASSWORD", None) MAX_STREAM_LENGTH = int(env("MAX_STREAM_LENGTH", 200)) -STREAMS = ["home", "local", "federated"] +STREAMS = ["home", "books"] # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 7eccfd651..3d39b9d52 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -23,6 +23,8 @@ STATUS_PATH = r"%s/(%s)/(?P\d+)" % (USER_PATH, "|".join(status_types) BOOK_PATH = r"^book/(?P\d+)" +STREAMS = "|".join(settings.STREAMS) + urlpatterns = [ path("admin/", admin.site.urls), path( @@ -177,7 +179,7 @@ urlpatterns = [ name="get-started-users", ), # feeds - re_path(r"^(?Phome|local|federated)/?$", views.Feed.as_view()), + re_path(r"^(?P{:s})/?$".format(STREAMS), views.Feed.as_view()), re_path( r"^direct-messages/?$", views.DirectMessage.as_view(), name="direct-messages" ), From 9d75bc39827d94319d50519e57890c03a677cb11 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 17:53:44 -0700 Subject: [PATCH 0094/1024] Display books timeline --- bookwyrm/activitystreams.py | 8 ++++---- bookwyrm/settings.py | 6 +++++- bookwyrm/templates/feed/feed.html | 24 +++++++----------------- bookwyrm/urls.py | 2 +- bookwyrm/views/feed.py | 9 +++++---- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 4e464b3cb..2f1555384 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -4,9 +4,9 @@ from django.db.models import signals, Q from bookwyrm import models from bookwyrm.redis_store import RedisStore, r +from bookwyrm.settings import STREAMS from bookwyrm.views.helpers import privacy_filter - class ActivityStream(RedisStore): """a category of activity stream (like home, local, federated)""" @@ -218,13 +218,13 @@ class BooksStream(ActivityStream): ) -streams = { +available_streams = [s["key"] for s in STREAMS] +streams = {k:v for (k, v) in { "home": HomeStream(), "local": LocalStream(), "federated": FederatedStream(), "books": BooksStream(), -} - +}.items() if k in available_streams} @receiver(signals.post_save) # pylint: disable=unused-argument diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index a10f128d6..180191d98 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -118,7 +118,11 @@ REDIS_ACTIVITY_PORT = env("REDIS_ACTIVITY_PORT", 6379) REDIS_ACTIVITY_PASSWORD = env("REDIS_ACTIVITY_PASSWORD", None) MAX_STREAM_LENGTH = int(env("MAX_STREAM_LENGTH", 200)) -STREAMS = ["home", "books"] + +STREAMS = [ + {"key": "home", "name": _("Home Timeline"), "shortname": _("Home")}, + {"key": "books", "name": _("Books Timeline"), "shortname": _("Books")}, +] # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 65cf97e19..780f1d171 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -4,35 +4,25 @@ {% block panel %}

- {% if tab == 'home' %} - {% trans "Home Timeline" %} - {% elif tab == 'local' %} - {% trans "Local Timeline" %} - {% else %} - {% trans "Federated Timeline" %} - {% endif %} + {{ tab.name }}

{# announcements and system messages #} {% if not activities.number > 1 %} -{% if request.user.show_goal and not goal and tab == 'home' %} +{% if request.user.show_goal and not goal and tab.key == streams.first.key %} {% now 'Y' as year %}
{% include 'snippets/goal_card.html' with year=year %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 3d39b9d52..d3e2dad1a 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -23,7 +23,7 @@ STATUS_PATH = r"%s/(%s)/(?P\d+)" % (USER_PATH, "|".join(status_types) BOOK_PATH = r"^book/(?P\d+)" -STREAMS = "|".join(settings.STREAMS) +STREAMS = "|".join(s["key"] for s in settings.STREAMS) urlpatterns = [ path("admin/", admin.site.urls), diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 3001c86e2..d28166a3f 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -23,10 +23,10 @@ class Feed(View): def get(self, request, tab): """user's homepage with activity feed""" - if not tab in STREAMS: - tab = "home" + tab = [s for s in STREAMS if s["key"] == tab] + tab = tab[0] or STREAMS[0] - activities = activitystreams.streams[tab].get_activity_stream(request.user) + activities = activitystreams.streams[tab["key"]].get_activity_stream(request.user) paginated = Paginator(activities, PAGE_LENGTH) suggestions = suggested_users.get_suggestions(request.user) @@ -38,8 +38,9 @@ class Feed(View): "activities": paginated.get_page(request.GET.get("page")), "suggested_users": suggestions, "tab": tab, + "streams": STREAMS, "goal_form": forms.GoalForm(), - "path": "/%s" % tab, + "path": "/%s" % tab["key"], }, } return TemplateResponse(request, "feed/feed.html", data) From 9d19092205bb2b0db2e120455e11edb563db9d80 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 18:22:06 -0700 Subject: [PATCH 0095/1024] Updates tests --- bookwyrm/activitystreams.py | 18 ++++++++++++------ .../tests/management/test_populate_streams.py | 2 +- bookwyrm/tests/views/test_feed.py | 2 +- bookwyrm/views/feed.py | 6 ++++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 2f1555384..0a9669719 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -7,6 +7,7 @@ from bookwyrm.redis_store import RedisStore, r from bookwyrm.settings import STREAMS from bookwyrm.views.helpers import privacy_filter + class ActivityStream(RedisStore): """a category of activity stream (like home, local, federated)""" @@ -219,12 +220,17 @@ class BooksStream(ActivityStream): available_streams = [s["key"] for s in STREAMS] -streams = {k:v for (k, v) in { - "home": HomeStream(), - "local": LocalStream(), - "federated": FederatedStream(), - "books": BooksStream(), -}.items() if k in available_streams} +streams = { + k: v + for (k, v) in { + "home": HomeStream(), + "local": LocalStream(), + "federated": FederatedStream(), + "books": BooksStream(), + }.items() + if k in available_streams +} + @receiver(signals.post_save) # pylint: disable=unused-argument diff --git a/bookwyrm/tests/management/test_populate_streams.py b/bookwyrm/tests/management/test_populate_streams.py index ee7a96d7c..c080e3fe5 100644 --- a/bookwyrm/tests/management/test_populate_streams.py +++ b/bookwyrm/tests/management/test_populate_streams.py @@ -46,4 +46,4 @@ class Activitystreams(TestCase): "bookwyrm.activitystreams.ActivityStream.populate_store" ) as redis_mock: populate_streams() - self.assertEqual(redis_mock.call_count, 6) # 2 users x 3 streams + self.assertEqual(redis_mock.call_count, 4) # 2 users x 2 streams diff --git a/bookwyrm/tests/views/test_feed.py b/bookwyrm/tests/views/test_feed.py index 8a38b808f..666c3e02b 100644 --- a/bookwyrm/tests/views/test_feed.py +++ b/bookwyrm/tests/views/test_feed.py @@ -45,7 +45,7 @@ class FeedViews(TestCase): view = views.Feed.as_view() request = self.factory.get("") request.user = self.local_user - result = view(request, "local") + result = view(request, "home") self.assertIsInstance(result, TemplateResponse) result.render() self.assertEqual(result.status_code, 200) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index d28166a3f..7a46ca57d 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -24,9 +24,11 @@ class Feed(View): def get(self, request, tab): """user's homepage with activity feed""" tab = [s for s in STREAMS if s["key"] == tab] - tab = tab[0] or STREAMS[0] + tab = tab[0] if tab else STREAMS[0] - activities = activitystreams.streams[tab["key"]].get_activity_stream(request.user) + activities = activitystreams.streams[tab["key"]].get_activity_stream( + request.user + ) paginated = Paginator(activities, PAGE_LENGTH) suggestions = suggested_users.get_suggestions(request.user) From 3b46ce85011b049f5ad8117ba98820b6250f5a31 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 18:57:05 -0700 Subject: [PATCH 0096/1024] Locale updates --- locale/de_DE/LC_MESSAGES/django.mo | Bin 24293 -> 24142 bytes locale/de_DE/LC_MESSAGES/django.po | 103 ++++++++++++++------------- locale/en_US/LC_MESSAGES/django.po | 90 ++++++++++++----------- locale/es/LC_MESSAGES/django.mo | Bin 43107 -> 42719 bytes locale/es/LC_MESSAGES/django.po | 101 ++++++++++++++------------ locale/fr_FR/LC_MESSAGES/django.mo | Bin 45939 -> 45471 bytes locale/fr_FR/LC_MESSAGES/django.po | 101 ++++++++++++++------------ locale/zh_Hans/LC_MESSAGES/django.mo | Bin 42356 -> 41974 bytes locale/zh_Hans/LC_MESSAGES/django.po | 100 ++++++++++++++------------ locale/zh_Hant/LC_MESSAGES/django.mo | Bin 41166 -> 40752 bytes locale/zh_Hant/LC_MESSAGES/django.po | 100 ++++++++++++++------------ 11 files changed, 321 insertions(+), 274 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index fb15184108c67c333088d8b27062a76939709a84..543d5355901e12d226dbe40f6d72ce8e7cf616f3 100644 GIT binary patch delta 7260 zcmaF5m+{;l#`=3gEK?a67#IQ=85m?37#QYoF)$niu|+|m3=9e~3=G8#3=E1g3=FLd z3=C6c7#R2%7#O5w85pz}7#Or<85lrHLuDBlq!}0(vSk?<3>X*~+GQCS_!$@&cE~a? zh%+!SoRDQ;kY!+Ccp%Hb5W>K~@K2V3L5+c-o*`HcB2gvBz@Wsyz%WCOfkBahfnm2C z#NfMf3=EPC3=E&;7#K_#7#MivAqG0hGce>cFfc?x=~MCy40#L;3|0yZ48aTx3@a5F z7#tWF82&0SFqkqhFxV+FFlaI`Fq9}VFbFd+Fw9eAU|?gYXJFW*$iTqCz`(Fmk%57k zfq~(WA_D^_0|Ub`MTieBK=}_8AwGWv*2uu{Q;~sz2NXz33=F&=hbciEF0I7CV8p<{ zV5`Kyz|O$HP@n{|h=HL(iGe|gfq|i3iGhKIfq`L?5(5K&Jp%*7bR`A`ZUzR1gWHuM4()@A&r@b#U}a!nSPhlm zs0?w)4k&#<8Dh=}Wd??Nkb$?9Awly-8R9}Q6^Ox_DiEI;s6ZTOrvkCqO9f&;I8;0n zDqgC>z#z}Sz|f=uv2YPoeihW5ZBTQMs4y^yFfcHjR$-_I2jK&#g10J=xc#ldz#zfE zz#yy&NmM$j5Q{xjAwCUNWni#iU|>j9g;+EXD!xn=;^1vi{t;D(!>_19qVxfjeg&n! zsMbRa{-?^oz{SA8z^w-1i>W~@QdWbA8>=xeNP!ZO8pPsAHAq^Rqy}-oLMXiwN^gY9 z?^J_Wd_s+ZL4kpR;SyB*vl=ALG1aR>;+R_Z1^b%=$*P<|4W zp99rb4b?YM9b)hdbx0~-2o>L|4)Mqybw~&uhllc4fTG$0|iO9Px+>KP7cFfgby zFfcrUYUI&`SR|#%zz_{8V4(aqO^AWhG$9UK3gvIqgrxQZnh+l!(}X0hTbhuNe6I3LcZAFtMe zbn3n_pufOgB$|`!zV2U23-aQ20?8G20>8%x7UWmaUe*5fq@}f8)8we zHpF2~+7ONNpz8K&Lo7V54e|j4!&PmF4IPSk<;AYTU(q>Va|pqvUdV2%#N;)Oa8i`MBtLTP| zgHBzDf&ID=pG?<ATBk4l-;cc5RFTr3O7ULcN;()cG>_E z0#^(m4!I2#e`)~9|L>ssSPUWN@EAg(NXihRU)_*_A(DZC!2lv(&(LKEamfrr1_m)u zEocY{>V1ZgY;wwwfx(M`f#C;~b~b|45q(CGT(Zmv;^W;$kOs^-BL)U11_p-LPa6l>d25AsUoSAwD%S zg;-E)3USaxQ-}}dLFtvIkf7dT3h~h?Q;5YEOc@w_85kIDm@+W(~NZv#K53y0nuP)0cpEA zL+Ke7kfzpK3rMZ#XbFjmDocpNdMzRPCtE@sIL8ta^h==Pt1TJo!A-9%P>H>kknD2A zl7S(Cfq~&3RHMBW#2|Mo1_n1q28IAD28ISu%gLI7p_74uLBa+SB8zMwseFeGB>O$F zfuxCVHVh1Ap!S3`Iy5F636OxkZk5>2Qj$B z4pM}+*)cF!GcYjBw}Zs#Z94{r8U_Z2-*yZPA z80;As7-Z`m85lGe7#Lz5A#vX32=VDGM@XD6c7)`Hbx`?Tju4B_IYJ!r+!5mQpN^13 z%I^g6p{x@mSLr!H8XmSz3=Fmm3=DBj5cB3ZLF}nt;RI>fY;=Oe(HSR*1y`IP2EKKI z1l4aRNQo!x3~{K0Go(?f;|$4$dz~TbFF8ZXg$K?MhrDuzq@CZ+5D#& zt1BcbnB5o{EJ1aM8^k<+H;6+c+`v9%$Z>;&NTnOZLtSnR41A#cKi3W7lQmEUd!P!= zLirEeAQpUdgM<*XJH#LfcSz4k)186Aih+T_-5u(1cZdTfxBAQr@WKpd9l0ZBU*9uRXH zp!z3!KzzR31LBY^9+0%OAFBSk2ekgb?*WOsmr#osJRxz!?g?>-uqVVIbx(-TO*|oK z#MKkxfM}??Tu+Eajh+yTdZ6?YPl(U=K+U}f<=^$Jhgk3lD#7Lj>D3B(L7GmsUJxJU zctH%P_hMj3V_;yI;svqbw-=s7F$ZsmK6fY`;|&S9LMUBT?+tNr zvp2*?ecq6eSmF%{`rY0TAK!o)@X{L+m;byWiIKwxqF%`d5;c}SkdSltfuyNmABaPe zeIV+yd?1Or1*)%pt`DSvu*HXgL7#zv;SN**k1xa^RbPlt4SgXRJ$)f1Vv;W;dv^Ll z65Tdmh|iDuLZa%1FCrvLzF+1K35k>b5Q`uALxTFXKg8j`q2kN|5D)MK zKtf0?01}m|0g$LN3t(VS0Ofy|0Eh!pp&AMUAO=+jKuWIW07w+92!O=(fdG)p85piZ z#qR|`9P$mS|9=1^L^%T?7V`%}Dkr%>h<>|3NSzQG$iPq!8lx$LO0)$+TsAilV!`S_ z28JRA28K<65C^ITLF5gCAaQLErGtVXK1+qlmjyx6NJ|hTBv%JPLTpD6B$r$af`sJL zAclHytCS-c;scXlhy}J#+B+DcFftet_cg(gAngl=7&Ido;?Olv{hNa!4&4(B3BeP= z5FcNFia&?y`wTUYJ)|C-3K=9rAPo+=5QxF`A&|5%IRsKWu7HXk4q;%h0}aK5FfjNq zFffRPLhAA4P)Ook912Mb2SXt~z6ce670STi&A`CG5e9KkNEpPS+4W(NxGE2W_@p)r z;=`6ONOtK9gE(kr7$juYLixL)2AvOs#PKsI|7#c|vGRmNJYXFTF()7#qAofd(g4W{ zXJAMH4Myz>hiH(Gfb@X;A|NfFq6mmjCPpwY1Tio$ER2A-{7VERPPro?v_vGtVXBc3 z3ymWoLGKX>@mN4414AeS14CFO14AGK1H+m~28J-u_+KQr%~;P68U-14>x+UII4O#O zAqv!_ih?No1?2}uGceeI42XtU_%a$2Qs1K?O)JJ2NE0q0hJhiTfq`L93}pOICKlqb z*jPvi7sW!-T4gNAq4f+5O;CX@C_OnAV(=WOhGnskkXakcz>vYfz;H1Z5~Nmf5QALf z7#J8CAWd!12qhkbu5Uz71VTRU|^^NjsG?>FfhDlfVA5|lAwX;s|*YbyFeT$ z1~rwTOfaoPDfFf%eRtN`nT z5TH&Eh_x3q{tFs<1#v)~%$W=f44I&TMFs|j$qWn(g`n{o1_p+o3=9k^jF7fHNUbAi zV2Xi(fsv7c;U%b@4-#a6bTUBAdC-WsDb&Y(pmsi}tN?XrK%Ec<28PQF3=A@i3=FNH z__u^AY-341jLK|-5A1Qag<%_ z!vO{chK&pi4Bb%m{)`L^{EQ3?%8U#Qw;321$`~Lc<>{dOZ_CKQpvTC-aDst>K?>@S z<4}#DAy@-O28QztkgU_g0O{=p#JU|P~iZIBT(Lk8mt6$2#5q?>kb!}r7b*rCJpfHn$TKo9%z}zthte<#G((XD<1jEVECx+&fPC!%3RDILhU&=| zrN!$(W5ys=MxgA;z`!sK#9@GxCpJ*4K}~lNMo4k|m4Si56{-d_iJ=Hp0~$AUXJBA> z#=yX!02R|^gw(pAK~j(wP$>;6I6;#oAif|YD0PFTYM>gHF+gTa5*Z*J6_6qr_JlD& zxr%{-;SZF5mVtpml97SIijjfgDFXw;Lz`)?i$iQ#|)RAFiU|0y6YhqwvFlS(3 z*vG)Yz|P3Pkj%iqkj=orpvlO?85kJ6p$-D6*$pBX7#K7d85ks>;-Co)P{a5?0|SF9Bcu`o zwIe}F)fgEV+CdCZf@fp^k43x&d6bcXL5Puoq23s3$Rto1z{tR`1T;GW8ir$lOiHa{ zfYg$Y86X210*sIbj}BBHXuimik%3_gXfzd6<}flaa5FM66hJLyWn^HmXJlYF&A`Ag z7b<4L2${|Cht!`83?)#B3k(blk3eGppuuOT7-)hD#QX*#p!f>|149**?aIi&a16?3 sV}#Vu4>!lkcrZ`CV=l1ymV6D@<`^w5(aHZEG&gUx_vP8l;d56A01RdKbN~PV delta 7413 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\n" "Language-Team: English \n" @@ -101,27 +101,49 @@ msgstr "Username" msgid "A user with that username already exists." msgstr "Dieser Benutzename ist bereits vergeben." -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:123 +msgid "Home Timeline" +msgstr "" + +#: bookwyrm/settings.py:123 +msgid "Home" +msgstr "" + +#: bookwyrm/settings.py:124 +#, fuzzy +#| msgid "Title" +msgid "Books Timeline" +msgstr "Titel" + +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +#, fuzzy +#| msgid "Book" +msgid "Books" +msgstr "Buch" + +#: bookwyrm/settings.py:170 msgid "English" msgstr "Englisch" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:171 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:172 msgid "Spanish" msgstr "Spanisch" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:173 msgid "French" msgstr "Französisch" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:174 msgid "Simplified Chinese" msgstr "Vereinfachtes Chinesisch" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:175 msgid "Traditional Chinese" msgstr "" @@ -972,39 +994,12 @@ msgstr "Alle Nachrichten" msgid "You have no messages right now." msgstr "Du hast momentan keine Nachrichten." -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:12 -#, fuzzy -#| msgid "Federated Servers" -msgid "Federated Timeline" -msgstr "Föderierende Server" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "Lokal" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "Föderiert" - -#: bookwyrm/templates/feed/feed.html:32 +#: bookwyrm/templates/feed/feed.html:22 #, python-format -msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "Hier sind noch keine Aktivitäten! Folge anderen, um loszulegen" @@ -2020,14 +2015,6 @@ msgstr "Suche nach Buch oder Benutzer*in" msgid "Search type" msgstr "Suche" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -#, fuzzy -#| msgid "Book" -msgid "Books" -msgstr "Buch" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2242,6 +2229,10 @@ msgstr "Instanzname" msgid "Status:" msgstr "Importstatus" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "Föderiert" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 #, fuzzy @@ -2573,15 +2564,23 @@ msgstr "Registrierungen geschlossen text" msgid "Posted by %(username)s" msgstr "Direktnachrichten mit %(username)s" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" +msgstr[1] "" + #: bookwyrm/templates/snippets/book_cover.html:32 #, fuzzy #| msgid "Add cover" msgid "No cover" msgstr "Cover hinzufügen" -#: bookwyrm/templates/snippets/book_titleby.html:4 -#, python-format -msgid "%(title)s by " +#: bookwyrm/templates/snippets/book_titleby.html:6 +#, fuzzy, python-format +#| msgid "%(title)s by " +msgid "%(title)s by" msgstr "%(title)s von " #: bookwyrm/templates/snippets/boost_button.html:20 @@ -3313,6 +3312,14 @@ msgstr "Dieser Benutzename ist bereits vergeben." msgid "A password reset link sent to %s" msgstr "" +#, fuzzy +#~| msgid "Federated Servers" +#~ msgid "Federated Timeline" +#~ msgstr "Föderierende Server" + +#~ msgid "Local" +#~ msgstr "Lokal" + #, fuzzy #~| msgid "Direct Messages with %(username)s" #~ msgid "Remove %(name)s" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index ce06013f2..153d8b9a1 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-04 20:40+0000\n" +"POT-Creation-Date: 2021-08-05 01:33+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -91,27 +91,45 @@ msgstr "" msgid "A user with that username already exists." msgstr "" -#: bookwyrm/settings.py:166 -msgid "English" +#: bookwyrm/settings.py:123 +msgid "Home Timeline" msgstr "" -#: bookwyrm/settings.py:167 -msgid "German" +#: bookwyrm/settings.py:123 +msgid "Home" msgstr "" -#: bookwyrm/settings.py:168 -msgid "Spanish" +#: bookwyrm/settings.py:124 +msgid "Books Timeline" msgstr "" -#: bookwyrm/settings.py:169 -msgid "French" +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +msgid "Books" msgstr "" #: bookwyrm/settings.py:170 -msgid "Simplified Chinese" +msgid "English" msgstr "" #: bookwyrm/settings.py:171 +msgid "German" +msgstr "" + +#: bookwyrm/settings.py:172 +msgid "Spanish" +msgstr "" + +#: bookwyrm/settings.py:173 +msgid "French" +msgstr "" + +#: bookwyrm/settings.py:174 +msgid "Simplified Chinese" +msgstr "" + +#: bookwyrm/settings.py:175 msgid "Traditional Chinese" msgstr "" @@ -896,37 +914,12 @@ msgstr "" msgid "You have no messages right now." msgstr "" -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:12 -msgid "Federated Timeline" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "" - -#: bookwyrm/templates/feed/feed.html:32 +#: bookwyrm/templates/feed/feed.html:22 #, python-format -msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "" @@ -1864,12 +1857,6 @@ msgstr "" msgid "Search type" msgstr "" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -msgid "Books" -msgstr "" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2045,6 +2032,10 @@ msgstr "" msgid "Status:" msgstr "" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 msgid "Blocked" @@ -2333,13 +2324,20 @@ msgstr "" msgid "Posted by %(username)s" msgstr "" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" +msgstr[1] "" + #: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "" -#: bookwyrm/templates/snippets/book_titleby.html:4 +#: bookwyrm/templates/snippets/book_titleby.html:6 #, python-format -msgid "%(title)s by " +msgid "%(title)s by" msgstr "" #: bookwyrm/templates/snippets/boost_button.html:20 diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index 69c734d46688d85bc60fa4b8f060ab0c9fbd8109..23869cf45428ccb9c4d7e0d8a06dc96b209e7775 100644 GIT binary patch delta 13188 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 diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index fd76f60d4..5bae4d7e2 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-04 20:40+0000\n" +"POT-Creation-Date: 2021-08-05 01:33+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -91,27 +91,47 @@ msgstr "nombre de usuario" msgid "A user with that username already exists." msgstr "Ya existe un usuario con ese nombre." -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:123 +msgid "Home Timeline" +msgstr "Línea temporal de hogar" + +#: bookwyrm/settings.py:123 +msgid "Home" +msgstr "Hogar" + +#: bookwyrm/settings.py:124 +#, fuzzy +#| msgid "Book Title" +msgid "Books Timeline" +msgstr "Título" + +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +msgid "Books" +msgstr "Libros" + +#: bookwyrm/settings.py:170 msgid "English" msgstr "Inglés" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:171 msgid "German" msgstr "Aléman" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:172 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:173 msgid "French" msgstr "Francés" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:174 msgid "Simplified Chinese" msgstr "Chino simplificado" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:175 #, fuzzy #| msgid "Additional info:" msgid "Traditional Chinese" @@ -904,37 +924,13 @@ msgstr "Todos los mensajes" msgid "You have no messages right now." msgstr "No tienes ningún mensaje en este momento." -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "Línea temporal de hogar" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "Línea temporal local" - -#: bookwyrm/templates/feed/feed.html:12 -msgid "Federated Timeline" -msgstr "Línea temporal federalizado" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "Hogar" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "Local" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "Federalizado" - -#: bookwyrm/templates/feed/feed.html:32 -#, python-format -msgid "load 0 unread status(es)" +#: bookwyrm/templates/feed/feed.html:22 +#, fuzzy, python-format +#| msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "cargar 0 status(es) no leídos" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "¡No hay actividad ahora mismo! Sigue a otro usuario para empezar" @@ -1885,12 +1881,6 @@ msgstr "Búsqueda" msgid "Search type" msgstr "Tipo de búsqueda" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -msgid "Books" -msgstr "Libros" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2072,6 +2062,10 @@ msgstr "Instancia:" msgid "Status:" msgstr "Status:" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "Federalizado" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 msgid "Blocked" @@ -2366,13 +2360,21 @@ msgstr "Texto de registración cerrada:" msgid "Posted by %(username)s" msgstr "Publicado por %(username)s" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" +msgstr[1] "" + #: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "Sin portada" -#: bookwyrm/templates/snippets/book_titleby.html:4 -#, python-format -msgid "%(title)s by " +#: bookwyrm/templates/snippets/book_titleby.html:6 +#, fuzzy, python-format +#| msgid "%(title)s by " +msgid "%(title)s by" msgstr "%(title)s por " #: bookwyrm/templates/snippets/boost_button.html:20 @@ -3047,6 +3049,15 @@ msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónic msgid "A password reset link sent to %s" msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" +#~ msgid "Local Timeline" +#~ msgstr "Línea temporal local" + +#~ msgid "Federated Timeline" +#~ msgstr "Línea temporal federalizado" + +#~ msgid "Local" +#~ msgstr "Local" + #~ msgid "Remove %(name)s" #~ msgstr "Eliminar %(name)s" diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 3d622ac662185de82e67b3026ad6d339fb8dab0a..f8ade2a391ba574da54afa6f45e1bf1ad55f9372 100644 GIT binary patch delta 13530 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\n" "Language-Team: Mouse Reeve \n" @@ -91,27 +91,47 @@ msgstr "nom du compte :" msgid "A user with that username already exists." msgstr "Ce nom est déjà associé à un compte." -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:123 +msgid "Home Timeline" +msgstr "Mon fil d’actualité" + +#: bookwyrm/settings.py:123 +msgid "Home" +msgstr "Accueil" + +#: bookwyrm/settings.py:124 +#, fuzzy +#| msgid "Book Title" +msgid "Books Timeline" +msgstr "Titre du livre" + +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +msgid "Books" +msgstr "Livres" + +#: bookwyrm/settings.py:170 msgid "English" msgstr "English" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:171 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:172 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:173 msgid "French" msgstr "Français" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:174 msgid "Simplified Chinese" msgstr "简化字" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:175 #, fuzzy #| msgid "Additional info:" msgid "Traditional Chinese" @@ -900,37 +920,13 @@ msgstr "Tous les messages" msgid "You have no messages right now." msgstr "Vous n’avez aucun message pour l’instant." -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "Mon fil d’actualité" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "Fil d’actualité local" - -#: bookwyrm/templates/feed/feed.html:12 -msgid "Federated Timeline" -msgstr "Fil d’actualité des instances fédérées" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "Accueil" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "Local" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "Fédéré" - -#: bookwyrm/templates/feed/feed.html:32 -#, python-format -msgid "load 0 unread status(es)" +#: bookwyrm/templates/feed/feed.html:22 +#, fuzzy, python-format +#| msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "charger le(s) 0 statut(s) non lu(s)" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "Aucune activité pour l’instant ! Abonnez‑vous à quelqu’un pour commencer" @@ -1879,12 +1875,6 @@ msgstr "Requête" msgid "Search type" msgstr "Type de recherche" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -msgid "Books" -msgstr "Livres" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2060,6 +2050,10 @@ msgstr "Instance :" msgid "Status:" msgstr "Statut :" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "Fédéré" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 msgid "Blocked" @@ -2348,13 +2342,21 @@ msgstr "Texte affiché lorsque les inscriptions sont closes :" msgid "Posted by %(username)s" msgstr "Publiée par %(username)s" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" +msgstr[1] "" + #: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "Pas de couverture" -#: bookwyrm/templates/snippets/book_titleby.html:4 -#, python-format -msgid "%(title)s by " +#: bookwyrm/templates/snippets/book_titleby.html:6 +#, fuzzy, python-format +#| msgid "%(title)s by " +msgid "%(title)s by" msgstr "%(title)s par " #: bookwyrm/templates/snippets/boost_button.html:20 @@ -3026,6 +3028,15 @@ msgstr "Aucun compte avec cette adresse email n’a été trouvé." msgid "A password reset link sent to %s" msgstr "Un lien de réinitialisation a été envoyé à %s." +#~ msgid "Local Timeline" +#~ msgstr "Fil d’actualité local" + +#~ msgid "Federated Timeline" +#~ msgstr "Fil d’actualité des instances fédérées" + +#~ msgid "Local" +#~ msgstr "Local" + #, fuzzy #~| msgid "BookWyrm users" #~ msgid "BookWyrm\\" diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index 3450c353ac4b48e9636805a6a77931a74b68dd92..6645033399a2ca839b8ebe71c829b209d23bfd31 100644 GIT binary patch delta 13776 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 delta 14090 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\n" "Language-Team: Mouse Reeve \n" @@ -91,27 +91,47 @@ msgstr "用户名" msgid "A user with that username already exists." msgstr "已经存在使用该用户名的用户。" -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:123 +msgid "Home Timeline" +msgstr "主页时间线" + +#: bookwyrm/settings.py:123 +msgid "Home" +msgstr "主页" + +#: bookwyrm/settings.py:124 +#, fuzzy +#| msgid "Book Title" +msgid "Books Timeline" +msgstr "书名" + +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +msgid "Books" +msgstr "书目" + +#: bookwyrm/settings.py:170 msgid "English" msgstr "English(英语)" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:171 msgid "German" msgstr "Deutsch(德语)" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:172 msgid "Spanish" msgstr "Español(西班牙语)" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:173 msgid "French" msgstr "Français(法语)" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:174 msgid "Simplified Chinese" msgstr "简体中文" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:175 msgid "Traditional Chinese" msgstr "繁體中文(繁体中文)" @@ -895,37 +915,13 @@ msgstr "所有消息" msgid "You have no messages right now." msgstr "你现在没有消息。" -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "主页时间线" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "本地时间线" - -#: bookwyrm/templates/feed/feed.html:12 -msgid "Federated Timeline" -msgstr "跨站时间线" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "主页" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "本站" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "跨站" - -#: bookwyrm/templates/feed/feed.html:32 -#, python-format -msgid "load 0 unread status(es)" +#: bookwyrm/templates/feed/feed.html:22 +#, fuzzy, python-format +#| msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "加载 0 条未读状态" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "现在还没有任何活动!尝试从关注一个用户开始吧" @@ -1865,12 +1861,6 @@ msgstr "搜索请求" msgid "Search type" msgstr "搜索类型" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -msgid "Books" -msgstr "书目" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2046,6 +2036,10 @@ msgstr "实例:" msgid "Status:" msgstr "状态:" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "跨站" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 msgid "Blocked" @@ -2334,13 +2328,20 @@ msgstr "注册关闭文字:" msgid "Posted by %(username)s" msgstr "由 %(username)s 发布" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" + #: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "没有封面" -#: bookwyrm/templates/snippets/book_titleby.html:4 -#, python-format -msgid "%(title)s by " +#: bookwyrm/templates/snippets/book_titleby.html:6 +#, fuzzy, python-format +#| msgid "%(title)s by " +msgid "%(title)s by" msgstr "%(title)s 来自" #: bookwyrm/templates/snippets/boost_button.html:20 @@ -3003,3 +3004,12 @@ msgstr "没有找到使用该邮箱的用户。" #, python-format msgid "A password reset link sent to %s" msgstr "密码重置连接已发送给 %s" + +#~ msgid "Local Timeline" +#~ msgstr "本地时间线" + +#~ msgid "Federated Timeline" +#~ msgstr "跨站时间线" + +#~ msgid "Local" +#~ msgstr "本站" diff --git a/locale/zh_Hant/LC_MESSAGES/django.mo b/locale/zh_Hant/LC_MESSAGES/django.mo index 8c8b5af887a30a2430d7a568e4e987d971a822fb..552fea2a6ea9d89a28105fe6338f09b8053c81ce 100644 GIT binary patch delta 13344 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 F1OQhtxN86a diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index b7736822f..5ce42251b 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-04 20:40+0000\n" +"POT-Creation-Date: 2021-08-05 01:33+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -91,27 +91,47 @@ msgstr "使用者名稱" msgid "A user with that username already exists." msgstr "已經存在使用該名稱的使用者。" -#: bookwyrm/settings.py:166 +#: bookwyrm/settings.py:123 +msgid "Home Timeline" +msgstr "主頁時間線" + +#: bookwyrm/settings.py:123 +msgid "Home" +msgstr "主頁" + +#: bookwyrm/settings.py:124 +#, fuzzy +#| msgid "Book Title" +msgid "Books Timeline" +msgstr "書名" + +#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/templates/search/layout.html:42 +#: bookwyrm/templates/user/layout.html:81 +msgid "Books" +msgstr "書目" + +#: bookwyrm/settings.py:170 msgid "English" msgstr "English(英語)" -#: bookwyrm/settings.py:167 +#: bookwyrm/settings.py:171 msgid "German" msgstr "Deutsch(德語)" -#: bookwyrm/settings.py:168 +#: bookwyrm/settings.py:172 msgid "Spanish" msgstr "Español(西班牙語)" -#: bookwyrm/settings.py:169 +#: bookwyrm/settings.py:173 msgid "French" msgstr "Français(法語)" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:174 msgid "Simplified Chinese" msgstr "簡體中文" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:175 #, fuzzy #| msgid "Tranditional Chinese" msgid "Traditional Chinese" @@ -901,37 +921,13 @@ msgstr "所有訊息" msgid "You have no messages right now." msgstr "你現在沒有訊息。" -#: bookwyrm/templates/feed/feed.html:8 -msgid "Home Timeline" -msgstr "主頁時間線" - -#: bookwyrm/templates/feed/feed.html:10 -msgid "Local Timeline" -msgstr "本地時間線" - -#: bookwyrm/templates/feed/feed.html:12 -msgid "Federated Timeline" -msgstr "跨站時間線" - -#: bookwyrm/templates/feed/feed.html:18 -msgid "Home" -msgstr "主頁" - -#: bookwyrm/templates/feed/feed.html:21 -msgid "Local" -msgstr "本站" - -#: bookwyrm/templates/feed/feed.html:24 -#: bookwyrm/templates/settings/edit_server.html:40 -msgid "Federated" -msgstr "跨站" - -#: bookwyrm/templates/feed/feed.html:32 -#, python-format -msgid "load 0 unread status(es)" +#: bookwyrm/templates/feed/feed.html:22 +#, fuzzy, python-format +#| msgid "load 0 unread status(es)" +msgid "load 0 unread status(es)" msgstr "載入 0 條未讀狀態" -#: bookwyrm/templates/feed/feed.html:48 +#: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" msgstr "現在還沒有任何活動!嘗試著從關注一個使用者開始吧" @@ -1880,12 +1876,6 @@ msgstr "搜尋請求" msgid "Search type" msgstr "搜尋類別" -#: bookwyrm/templates/search/layout.html:21 -#: bookwyrm/templates/search/layout.html:42 -#: bookwyrm/templates/user/layout.html:81 -msgid "Books" -msgstr "書目" - #: bookwyrm/templates/search/layout.html:23 #: bookwyrm/templates/search/layout.html:46 #: bookwyrm/templates/settings/admin_layout.html:26 @@ -2061,6 +2051,10 @@ msgstr "實例:" msgid "Status:" msgstr "狀態:" +#: bookwyrm/templates/settings/edit_server.html:40 +msgid "Federated" +msgstr "跨站" + #: bookwyrm/templates/settings/edit_server.html:41 #: bookwyrm/templates/settings/federated_server.html:10 msgid "Blocked" @@ -2353,13 +2347,20 @@ msgstr "註冊關閉文字:" msgid "Posted by %(username)s" msgstr "由 %(username)s 釋出" +#: bookwyrm/templates/snippets/authors.html:22 +#, python-format +msgid "and %(remainder_count_display)s other" +msgid_plural "and %(remainder_count_display)s others" +msgstr[0] "" + #: bookwyrm/templates/snippets/book_cover.html:32 msgid "No cover" msgstr "沒有封面" -#: bookwyrm/templates/snippets/book_titleby.html:4 -#, python-format -msgid "%(title)s by " +#: bookwyrm/templates/snippets/book_titleby.html:6 +#, fuzzy, python-format +#| msgid "%(title)s by " +msgid "%(title)s by" msgstr "%(title)s 來自" #: bookwyrm/templates/snippets/boost_button.html:20 @@ -3023,5 +3024,14 @@ msgstr "沒有找到使用該郵箱的使用者。" msgid "A password reset link sent to %s" msgstr "密碼重置連結已傳送給 %s" +#~ msgid "Local Timeline" +#~ msgstr "本地時間線" + +#~ msgid "Federated Timeline" +#~ msgstr "跨站時間線" + +#~ msgid "Local" +#~ msgstr "本站" + #~ msgid "Remove %(name)s" #~ msgstr "移除 %(name)s" From 75f586c10983e70169df495b835d4ffa58757454 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 19:09:00 -0700 Subject: [PATCH 0097/1024] Removes unused stream code --- bookwyrm/activitystreams.py | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 0a9669719..b4926285f 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -156,25 +156,6 @@ class LocalStream(ActivityStream): ) -class FederatedStream(ActivityStream): - """users you follow""" - - key = "federated" - - def get_audience(self, status): - # this stream wants no part in non-public statuses - if status.privacy != "public": - return [] - return super().get_audience(status) - - def get_statuses_for_user(self, user): - return privacy_filter( - user, - models.Status.objects.select_subclasses(), - privacy_levels=["public"], - ) - - class BooksStream(ActivityStream): """books on your shelves""" @@ -201,7 +182,7 @@ class BooksStream(ActivityStream): return audience.filter(shelfbook__book__parent_work=work).distinct() def get_statuses_for_user(self, user): - """any public status that mentions their books""" + """any public status that mentions the user's books""" books = user.shelfbook_set.values_list( "book__parent_work__id", flat=True ).distinct() @@ -219,13 +200,13 @@ class BooksStream(ActivityStream): ) +# determine which streams are enabled in settings.py available_streams = [s["key"] for s in STREAMS] streams = { k: v for (k, v) in { "home": HomeStream(), "local": LocalStream(), - "federated": FederatedStream(), "books": BooksStream(), }.items() if k in available_streams From 1c0472efc2835d15072d5346df1e39dda555846a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 19:19:24 -0700 Subject: [PATCH 0098/1024] Fixes references to public streams --- bookwyrm/activitystreams.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index b4926285f..7c15fd900 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -9,7 +9,7 @@ from bookwyrm.views.helpers import privacy_filter class ActivityStream(RedisStore): - """a category of activity stream (like home, local, federated)""" + """a category of activity stream (like home, local, books)""" def stream_id(self, user): """the redis key for this user's instance of this stream""" @@ -229,7 +229,6 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): if not created: return - # iterates through Home, Local, Federated for stream in streams.values(): stream.add_status(instance) @@ -296,7 +295,7 @@ def remove_statuses_on_block(sender, instance, *args, **kwargs): # pylint: disable=unused-argument def add_statuses_on_unblock(sender, instance, *args, **kwargs): """remove statuses from all feeds on block""" - public_streams = [LocalStream(), FederatedStream()] + public_streams = [v for (k, v) in streams.items() if k != 'home'] # add statuses back to streams with statuses from anyone if instance.user_subject.local: for stream in public_streams: From c8250ac94cf342567207b473eb06cb56426b9c59 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 19:25:44 -0700 Subject: [PATCH 0099/1024] Python formatting --- bookwyrm/activitystreams.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 7c15fd900..01ca3f770 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -295,7 +295,7 @@ def remove_statuses_on_block(sender, instance, *args, **kwargs): # pylint: disable=unused-argument def add_statuses_on_unblock(sender, instance, *args, **kwargs): """remove statuses from all feeds on block""" - public_streams = [v for (k, v) in streams.items() if k != 'home'] + public_streams = [v for (k, v) in streams.items() if k != "home"] # add statuses back to streams with statuses from anyone if instance.user_subject.local: for stream in public_streams: From 1fbca70820af0434f46be4b33ea324f6ce4b7524 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 19:54:47 -0700 Subject: [PATCH 0100/1024] Move activitystreams updates to tasks --- bookwyrm/activitystreams.py | 116 +++++++++++++++++++++++++++--------- celerywyrm/celery.py | 1 + 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index a49a7ce4d..543a8a7e1 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -1,9 +1,11 @@ """ access the activity streams stored in redis """ from django.dispatch import receiver +from django.db import transaction from django.db.models import signals, Q from bookwyrm import models from bookwyrm.redis_store import RedisStore, r +from bookwyrm.tasks import app from bookwyrm.views.helpers import privacy_filter @@ -190,16 +192,20 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): return if instance.deleted: - for stream in streams.values(): - stream.remove_object_from_related_stores(instance) + remove_status_task.delay(instance.id) return if not created: return + # when creating new things, gotta wait on the transaction + transaction.on_commit(lambda: add_status_on_create_command(sender, instance)) + + +def add_status_on_create_command(sender, instance): + """runs this code only after the database commit completes""" # iterates through Home, Local, Federated - for stream in streams.values(): - stream.add_status(instance) + add_status_task.delay(instance.id) if sender != models.Boost: return @@ -208,23 +214,19 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): 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) + ).values_list("id", flat=True) + remove_status_task.delay(boosted.id) + remove_status_task.delay(old_versions) @receiver(signals.post_delete, sender=models.Boost) # pylint: disable=unused-argument 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) + # remove the boost + remove_status_task.delay(instance.id) + # re-add the original status + add_status_task.delay(instance.boosted_status.id) @receiver(signals.post_save, sender=models.UserFollows) @@ -233,7 +235,9 @@ def add_statuses_on_follow(sender, instance, created, *args, **kwargs): """add a newly followed user's statuses to feeds""" if not created or not instance.user_subject.local: return - HomeStream().add_user_statuses(instance.user_subject, instance.user_object) + add_user_statuses_task.delay( + instance.user_subject.id, instance.user_object.id, stream_list=["home"] + ) @receiver(signals.post_delete, sender=models.UserFollows) @@ -242,7 +246,9 @@ def remove_statuses_on_unfollow(sender, instance, *args, **kwargs): """remove statuses from a feed on unfollow""" if not instance.user_subject.local: return - HomeStream().remove_user_statuses(instance.user_subject, instance.user_object) + remove_user_statuses_task.delay( + instance.user_subject.id, instance.user_object.id, stream_list=["home"] + ) @receiver(signals.post_save, sender=models.UserBlocks) @@ -251,29 +257,36 @@ def remove_statuses_on_block(sender, instance, *args, **kwargs): """remove statuses from all feeds on block""" # blocks apply ot all feeds if instance.user_subject.local: - for stream in streams.values(): - stream.remove_user_statuses(instance.user_subject, instance.user_object) + remove_user_statuses_task.delay( + instance.user_subject.id, instance.user_object.id + ) # and in both directions if instance.user_object.local: - for stream in streams.values(): - stream.remove_user_statuses(instance.user_object, instance.user_subject) + remove_user_statuses_task.delay( + instance.user_object.id, instance.user_subject.id + ) @receiver(signals.post_delete, sender=models.UserBlocks) # pylint: disable=unused-argument def add_statuses_on_unblock(sender, instance, *args, **kwargs): """remove statuses from all feeds on block""" - public_streams = [LocalStream(), FederatedStream()] # add statuses back to streams with statuses from anyone if instance.user_subject.local: - for stream in public_streams: - stream.add_user_statuses(instance.user_subject, instance.user_object) + add_user_statuses_task.delay( + instance.user_subject.id, + instance.user_object.id, + stream_list=["local", "federated"], + ) # add statuses back to streams with statuses from anyone if instance.user_object.local: - for stream in public_streams: - stream.add_user_statuses(instance.user_object, instance.user_subject) + add_user_statuses_task.delay( + instance.user_object.id, + instance.user_subject.id, + stream_list=["local", "federated"], + ) @receiver(signals.post_save, sender=models.User) @@ -283,5 +296,54 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg if not created or not instance.local: return + populate_streams_task.delay(instance.id) + + +# ---- TASKS + +@app.task +def populate_streams_task(user_id): + """create a user's streams""" + user = models.User.objects.get(id=user_id) for stream in streams.values(): - stream.populate_streams(instance) + stream.populate_streams(user) + +@app.task +def remove_status_task(status_ids): + """remove a status from any stream it might be in""" + # this can take an id or a list of ids + if not isinstance(status_ids, list): + status_ids = [status_ids] + statuses = models.Status.objects.filter(id__in=status_ids) + + for stream in streams.values(): + for status in statuses: + stream.remove_object_from_related_stores(status) + + +@app.task +def add_status_task(status_id): + """remove a status from any stream it might be in""" + status = models.Status.objects.get(id=status_id) + for stream in streams.values(): + stream.add_status(status) + + +@app.task +def remove_user_statuses_task(viewer_id, user_id, stream_list=None): + """remove all statuses by a user from a viewer's stream""" + stream_list = [streams[s] for s in stream_list] if stream_list else streams.values() + viewer = models.User.objects.get(id=viewer_id) + user = models.User.objects.get(id=user_id) + for stream in stream_list: + stream.remove_user_statuses(viewer, user) + + +@app.task +def add_user_statuses_task(viewer_id, user_id, stream_list=None): + """remove all statuses by a user from a viewer's stream""" + stream_list = [streams[s] for s in stream_list] if stream_list else streams.values() + viewer = models.User.objects.get(id=viewer_id) + user = models.User.objects.get(id=user_id) + for stream in stream_list: + stream.add_user_statuses(viewer, user) diff --git a/celerywyrm/celery.py b/celerywyrm/celery.py index 3ab338621..de5e56304 100644 --- a/celerywyrm/celery.py +++ b/celerywyrm/celery.py @@ -20,6 +20,7 @@ app.config_from_object("django.conf:settings", namespace="CELERY") # Load task modules from all registered Django app configs. app.autodiscover_tasks() app.autodiscover_tasks(["bookwyrm"], related_name="activitypub.base_activity") +app.autodiscover_tasks(["bookwyrm"], related_name="activitystreams") app.autodiscover_tasks(["bookwyrm"], related_name="broadcast") app.autodiscover_tasks(["bookwyrm"], related_name="connectors.abstract_connector") app.autodiscover_tasks(["bookwyrm"], related_name="emailing") From 6841a66e76c3acd45acc3e56bf310f1bad6763db Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 19:57:39 -0700 Subject: [PATCH 0101/1024] Python formatting --- bookwyrm/activitystreams.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 543a8a7e1..4e48a0444 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -301,6 +301,7 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg # ---- TASKS + @app.task def populate_streams_task(user_id): """create a user's streams""" @@ -308,6 +309,7 @@ def populate_streams_task(user_id): for stream in streams.values(): stream.populate_streams(user) + @app.task def remove_status_task(status_ids): """remove a status from any stream it might be in""" From 142d0da3b73a5a5f679c187771c58392b0169ce1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 4 Aug 2021 20:01:44 -0700 Subject: [PATCH 0102/1024] Removes outdated tests --- bookwyrm/tests/test_activitystreams.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py index f4747971a..22445892e 100644 --- a/bookwyrm/tests/test_activitystreams.py +++ b/bookwyrm/tests/test_activitystreams.py @@ -190,20 +190,3 @@ class Activitystreams(TestCase): ) users = activitystreams.LocalStream().get_audience(status) self.assertEqual(users, []) - - def test_federatedstream_get_audience(self, *_): - """get a list of users that should see a status""" - status = models.Status.objects.create( - user=self.remote_user, content="hi", privacy="public" - ) - users = activitystreams.FederatedStream().get_audience(status) - self.assertTrue(self.local_user in users) - self.assertTrue(self.another_user in users) - - def test_federatedstream_get_audience_unlisted(self, *_): - """get a list of users that should see a status""" - status = models.Status.objects.create( - user=self.remote_user, content="hi", privacy="unlisted" - ) - users = activitystreams.FederatedStream().get_audience(status) - self.assertEqual(users, []) From f3a757951cdb40364546b843577c29ca5a3c0b3a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 14:22:54 -0700 Subject: [PATCH 0103/1024] Tests for books stream --- bookwyrm/tests/test_activitystreams.py | 97 +++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py index 22445892e..ba4950895 100644 --- a/bookwyrm/tests/test_activitystreams.py +++ b/bookwyrm/tests/test_activitystreams.py @@ -6,6 +6,7 @@ from bookwyrm import activitystreams, models @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") @patch("bookwyrm.activitystreams.ActivityStream.add_status") +@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") class Activitystreams(TestCase): """using redis to build activity streams""" @@ -32,7 +33,8 @@ class Activitystreams(TestCase): inbox="https://example.com/users/rat/inbox", outbox="https://example.com/users/rat/outbox", ) - self.book = models.Edition.objects.create(title="test book") + work = models.Work.objects.create(title="test work") + self.book = models.Edition.objects.create(title="test book", parent_work=work) class TestStream(activitystreams.ActivityStream): """test stream, don't have to do anything here""" @@ -190,3 +192,96 @@ class Activitystreams(TestCase): ) users = activitystreams.LocalStream().get_audience(status) self.assertEqual(users, []) + + def test_localstream_get_audience_books_no_book(self, *_): + """get a list of users that should see a status""" + status = models.Status.objects.create( + user=self.local_user, content="hi", privacy="public" + ) + audience = activitystreams.BooksStream().get_audience(status) + # no books, no audience + self.assertEqual(audience, []) + + def test_localstream_get_audience_books_mention_books(self, *_): + """get a list of users that should see a status""" + status = models.Status.objects.create( + user=self.local_user, content="hi", privacy="public" + ) + status.mention_books.add(self.book) + status.save(broadcast=False) + models.ShelfBook.objects.create( + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + book=self.book, + ) + # yes book, yes audience + audience = activitystreams.BooksStream().get_audience(status) + self.assertTrue(self.local_user in audience) + + def test_localstream_get_audience_books_book_field(self, *_): + """get a list of users that should see a status""" + status = models.Comment.objects.create( + user=self.local_user, content="hi", privacy="public", book=self.book + ) + models.ShelfBook.objects.create( + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + book=self.book, + ) + # yes book, yes audience + audience = activitystreams.BooksStream().get_audience(status) + self.assertTrue(self.local_user in audience) + + def test_localstream_get_audience_books_alternate_edition(self, *_): + """get a list of users that should see a status""" + alt_book = models.Edition.objects.create( + title="hi", parent_work=self.book.parent_work + ) + status = models.Comment.objects.create( + user=self.remote_user, content="hi", privacy="public", book=alt_book + ) + models.ShelfBook.objects.create( + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + book=self.book, + ) + # yes book, yes audience + audience = activitystreams.BooksStream().get_audience(status) + self.assertTrue(self.local_user in audience) + + def test_localstream_get_audience_books_non_public(self, *_): + """get a list of users that should see a status""" + alt_book = models.Edition.objects.create( + title="hi", parent_work=self.book.parent_work + ) + status = models.Comment.objects.create( + user=self.remote_user, content="hi", privacy="unlisted", book=alt_book + ) + models.ShelfBook.objects.create( + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + book=self.book, + ) + # yes book, yes audience + audience = activitystreams.BooksStream().get_audience(status) + self.assertEqual(audience, []) + + def test_get_statuses_for_user_books(self, *_): + """create a stream for a user""" + alt_book = models.Edition.objects.create( + title="hi", parent_work=self.book.parent_work + ) + status = models.Status.objects.create( + user=self.local_user, content="hi", privacy="public" + ) + status = models.Comment.objects.create( + user=self.remote_user, content="hi", privacy="public", book=alt_book + ) + models.ShelfBook.objects.create( + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + book=self.book, + ) + # yes book, yes audience + result = activitystreams.BooksStream().get_statuses_for_user(self.local_user) + self.assertEqual(list(result), [status]) From 30288c6ebb362feb5e05e51d1cd09787dd13fbd7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 16:39:09 -0700 Subject: [PATCH 0104/1024] Update books feed on shelve --- bookwyrm/activitystreams.py | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 01ca3f770..6b75a65fa 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -199,6 +199,40 @@ class BooksStream(ActivityStream): privacy_levels=["public"], ) + def add_book_statuses(self, user, book): + """add statuses about a book to a user's feed""" + work = book.parent_work + statuses = privacy_filter( + user, + models.Status.objects.select_subclasses() + .filter( + Q(comment__book__parent_work=work) + | Q(quotation__book__parent_work=work) + | Q(review__book__parent_work=work) + | Q(mention_books__parent_work=work) + ) + .distinct(), + privacy_levels=["public"], + ) + self.bulk_add_objects_to_store(statuses, self.stream_id(user)) + + def remove_book_statuses(self, user, book): + """add statuses about a book to a user's feed""" + work = book.parent_work + statuses = privacy_filter( + user, + models.Status.objects.select_subclasses() + .filter( + Q(comment__book__parent_work=work) + | Q(quotation__book__parent_work=work) + | Q(review__book__parent_work=work) + | Q(mention_books__parent_work=work) + ) + .distinct(), + privacy_levels=["public"], + ) + self.bulk_remove_objects_from_store(statuses, self.stream_id(user)) + # determine which streams are enabled in settings.py available_streams = [s["key"] for s in STREAMS] @@ -316,3 +350,33 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg for stream in streams.values(): stream.populate_streams(instance) + + +@receiver(signals.pre_save, sender=models.ShelfBook) +# pylint: disable=unused-argument +def add_statuses_on_shelve(sender, instance, created, *args, **kwargs): + """update books stream when user shelves a book""" + if not created or not instance.user.local: + return + # check if the book is already on the user's shelves + if models.ShelfBook.objects.filter( + user=instance.user, book__in=instance.book.parent_work.editions.all() + ).exists(): + return + + BooksStream().add_book_statuses(instance.user, instance.book) + + +@receiver(signals.post_delete, sender=models.ShelfBook) +# pylint: disable=unused-argument +def remove_statuses_on_shelve(sender, instance, *args, **kwargs): + """update books stream when user unshelves a book""" + if not instance.user.local: + return + # check if the book is actually unshelved, not just moved + if models.ShelfBook.objects.filter( + user=instance.user, book__in=instance.book.parent_work.editions.all() + ).exists(): + return + + BooksStream().remove_book_statuses(instance.user, instance.book) From 70f4ecf870dd269da4b123e1682385466a904d9e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:13:47 -0700 Subject: [PATCH 0105/1024] Removes invalid argument --- bookwyrm/activitystreams.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 6b75a65fa..bad7c59f8 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -354,9 +354,9 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg @receiver(signals.pre_save, sender=models.ShelfBook) # pylint: disable=unused-argument -def add_statuses_on_shelve(sender, instance, created, *args, **kwargs): +def add_statuses_on_shelve(sender, instance, *args, **kwargs): """update books stream when user shelves a book""" - if not created or not instance.user.local: + if not instance.user.local: return # check if the book is already on the user's shelves if models.ShelfBook.objects.filter( From 70a535adb7c36395a6f63587817b1730762297cc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:19:39 -0700 Subject: [PATCH 0106/1024] Adds books stream mock --- bookwyrm/tests/test_activitystreams.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py index ba4950895..ac57d8b3d 100644 --- a/bookwyrm/tests/test_activitystreams.py +++ b/bookwyrm/tests/test_activitystreams.py @@ -6,6 +6,7 @@ from bookwyrm import activitystreams, models @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") @patch("bookwyrm.activitystreams.ActivityStream.add_status") +@patch("bookwyrm.activitystreams.BooksStream.add_book_statuses") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") class Activitystreams(TestCase): """using redis to build activity streams""" From d390b395e69e515fe13f36ec4a6081570c4f1865 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:47:28 -0700 Subject: [PATCH 0107/1024] fixes book mock in user view tests --- bookwyrm/tests/views/test_edit_user.py | 4 +++- bookwyrm/tests/views/test_user.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_edit_user.py b/bookwyrm/tests/views/test_edit_user.py index ccfb4c90d..df89d5b09 100644 --- a/bookwyrm/tests/views/test_edit_user.py +++ b/bookwyrm/tests/views/test_edit_user.py @@ -34,7 +34,9 @@ class EditUserViews(TestCase): "rat@local.com", "rat@rat.rat", "password", local=True, localname="rat" ) - self.book = models.Edition.objects.create(title="test") + self.book = models.Edition.objects.create( + title="test", parent_work=models.Work.objects.create(title="test work") + ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): models.ShelfBook.objects.create( book=self.book, diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py index 0efdf16a3..740f0d299 100644 --- a/bookwyrm/tests/views/test_user.py +++ b/bookwyrm/tests/views/test_user.py @@ -28,7 +28,9 @@ class UserViews(TestCase): 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") + self.book = models.Edition.objects.create( + title="test", parent_work=models.Work.objects.create(title="test work") + ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): models.ShelfBook.objects.create( From d0114d2e8353025c1288cd34d0ac2f3ef5add3da Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 18:05:57 -0700 Subject: [PATCH 0108/1024] Adds test for book add description view --- bookwyrm/tests/views/test_book.py | 12 ++++++++++++ bookwyrm/views/books.py | 9 +++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 6f6116b2e..51f8b5d56 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -299,3 +299,15 @@ class BookViews(TestCase): self.book.refresh_from_db() self.assertTrue(self.book.cover) + + def test_add_description(self): + """add a book description""" + self.local_user.groups.add(self.group) + request = self.factory.post("", {"description": "new description hi"}) + request.user = self.local_user + + views.add_description(request, self.book.id) + + self.book.refresh_from_db() + self.assertEqual(self.book.description, "new description hi") + self.assertEqual(self.book.last_edited_by, self.local_user) diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 492d0cac4..d56e2f22c 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -339,18 +339,15 @@ def set_cover_from_url(url): @permission_required("bookwyrm.edit_book", raise_exception=True) def add_description(request, book_id): """upload a new cover""" - if not request.method == "POST": - return redirect("/") - book = get_object_or_404(models.Edition, id=book_id) description = request.POST.get("description") book.description = description book.last_edited_by = request.user - book.save() + book.save(update_fields=["description", "last_edited_by"]) - return redirect("/book/%s" % book.id) + return redirect("book", book.id) @require_POST @@ -360,7 +357,7 @@ def resolve_book(request): connector = connector_manager.get_or_create_connector(remote_id) book = connector.get_or_create_book(remote_id) - return redirect("/book/%d" % book.id) + return redirect("book", book.id) @login_required From 41742d6698074e29ba4077fb04a296cd4841ce74 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 18:16:23 -0700 Subject: [PATCH 0109/1024] Adds inventaire get connector test --- .../tests/connectors/test_inventaire_connector.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bookwyrm/tests/connectors/test_inventaire_connector.py b/bookwyrm/tests/connectors/test_inventaire_connector.py index c66f0400d..381017727 100644 --- a/bookwyrm/tests/connectors/test_inventaire_connector.py +++ b/bookwyrm/tests/connectors/test_inventaire_connector.py @@ -171,3 +171,15 @@ class Inventaire(TestCase): } self.assertEqual(get_language_code(options), "there") self.assertIsNone(get_language_code({})) + + @responses.activate + def test_get_description(self): + """extract a wikipedia excerpt""" + responses.add( + responses.GET, + "https://inventaire.io/api/data?action=wp-extract&lang=en&title=test_path", + json={"extract": "hi hi"}, + ) + + extract = self.connector.get_description({"enwiki": "test_path"}) + self.assertEqual(extract, "hi hi") From 48175023bcad05526479c5830ed4cd25c30a53de Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 18:58:32 -0700 Subject: [PATCH 0110/1024] Mocks broadcast --- bookwyrm/tests/views/test_book.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 51f8b5d56..3b6748523 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -306,7 +306,8 @@ class BookViews(TestCase): request = self.factory.post("", {"description": "new description hi"}) request.user = self.local_user - views.add_description(request, self.book.id) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + views.add_description(request, self.book.id) self.book.refresh_from_db() self.assertEqual(self.book.description, "new description hi") From 120938bee98725cf4c490b9d607147d04e246152 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 19:28:05 -0700 Subject: [PATCH 0111/1024] Update books feed on shelve --- bookwyrm/activitystreams.py | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 961b9797c..4137c6bf6 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -201,6 +201,40 @@ class BooksStream(ActivityStream): privacy_levels=["public"], ) + def add_book_statuses(self, user, book): + """add statuses about a book to a user's feed""" + work = book.parent_work + statuses = privacy_filter( + user, + models.Status.objects.select_subclasses() + .filter( + Q(comment__book__parent_work=work) + | Q(quotation__book__parent_work=work) + | Q(review__book__parent_work=work) + | Q(mention_books__parent_work=work) + ) + .distinct(), + privacy_levels=["public"], + ) + self.bulk_add_objects_to_store(statuses, self.stream_id(user)) + + def remove_book_statuses(self, user, book): + """add statuses about a book to a user's feed""" + work = book.parent_work + statuses = privacy_filter( + user, + models.Status.objects.select_subclasses() + .filter( + Q(comment__book__parent_work=work) + | Q(quotation__book__parent_work=work) + | Q(review__book__parent_work=work) + | Q(mention_books__parent_work=work) + ) + .distinct(), + privacy_levels=["public"], + ) + self.bulk_remove_objects_from_store(statuses, self.stream_id(user)) + # determine which streams are enabled in settings.py available_streams = [s["key"] for s in STREAMS] @@ -331,6 +365,36 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg populate_streams_task.delay(instance.id) +@receiver(signals.pre_save, sender=models.ShelfBook) +# pylint: disable=unused-argument +def add_statuses_on_shelve(sender, instance, created, *args, **kwargs): + """update books stream when user shelves a book""" + if not created or not instance.user.local: + return + # check if the book is already on the user's shelves + if models.ShelfBook.objects.filter( + user=instance.user, book__in=instance.book.parent_work.editions.all() + ).exists(): + return + + BooksStream().add_book_statuses(instance.user, instance.book) + + +@receiver(signals.post_delete, sender=models.ShelfBook) +# pylint: disable=unused-argument +def remove_statuses_on_shelve(sender, instance, *args, **kwargs): + """update books stream when user unshelves a book""" + if not instance.user.local: + return + # check if the book is actually unshelved, not just moved + if models.ShelfBook.objects.filter( + user=instance.user, book__in=instance.book.parent_work.editions.all() + ).exists(): + return + + BooksStream().remove_book_statuses(instance.user, instance.book) + + # ---- TASKS From 061deaefda40ca3016514a6d514373a0f0b19b71 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:13:47 -0700 Subject: [PATCH 0112/1024] Removes invalid argument --- bookwyrm/activitystreams.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 4137c6bf6..ebe2cbd97 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -367,9 +367,9 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg @receiver(signals.pre_save, sender=models.ShelfBook) # pylint: disable=unused-argument -def add_statuses_on_shelve(sender, instance, created, *args, **kwargs): +def add_statuses_on_shelve(sender, instance, *args, **kwargs): """update books stream when user shelves a book""" - if not created or not instance.user.local: + if not instance.user.local: return # check if the book is already on the user's shelves if models.ShelfBook.objects.filter( From 6b7e3f2061d38c131a4098575e0edd6bf4595c21 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:19:39 -0700 Subject: [PATCH 0113/1024] Adds books stream mock --- bookwyrm/tests/test_activitystreams.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py index ba4950895..ac57d8b3d 100644 --- a/bookwyrm/tests/test_activitystreams.py +++ b/bookwyrm/tests/test_activitystreams.py @@ -6,6 +6,7 @@ from bookwyrm import activitystreams, models @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") @patch("bookwyrm.activitystreams.ActivityStream.add_status") +@patch("bookwyrm.activitystreams.BooksStream.add_book_statuses") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") class Activitystreams(TestCase): """using redis to build activity streams""" From b3fa8de65aaf547edadaec224e9f39a01298b79c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 17:47:28 -0700 Subject: [PATCH 0114/1024] fixes book mock in user view tests --- bookwyrm/tests/views/test_edit_user.py | 4 +++- bookwyrm/tests/views/test_user.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_edit_user.py b/bookwyrm/tests/views/test_edit_user.py index ccfb4c90d..df89d5b09 100644 --- a/bookwyrm/tests/views/test_edit_user.py +++ b/bookwyrm/tests/views/test_edit_user.py @@ -34,7 +34,9 @@ class EditUserViews(TestCase): "rat@local.com", "rat@rat.rat", "password", local=True, localname="rat" ) - self.book = models.Edition.objects.create(title="test") + self.book = models.Edition.objects.create( + title="test", parent_work=models.Work.objects.create(title="test work") + ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): models.ShelfBook.objects.create( book=self.book, diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py index 0efdf16a3..740f0d299 100644 --- a/bookwyrm/tests/views/test_user.py +++ b/bookwyrm/tests/views/test_user.py @@ -28,7 +28,9 @@ class UserViews(TestCase): 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") + self.book = models.Edition.objects.create( + title="test", parent_work=models.Work.objects.create(title="test work") + ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): models.ShelfBook.objects.create( From 2e7dd9d4ef0018dcaba5e8ecbf158e813eb5051e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 5 Aug 2021 19:51:31 -0700 Subject: [PATCH 0115/1024] Fixes over-reporting user last active date --- .../0081_alter_user_last_active_date.py | 19 +++++++++++++++++++ bookwyrm/models/user.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/migrations/0081_alter_user_last_active_date.py diff --git a/bookwyrm/migrations/0081_alter_user_last_active_date.py b/bookwyrm/migrations/0081_alter_user_last_active_date.py new file mode 100644 index 000000000..dc6b640f6 --- /dev/null +++ b/bookwyrm/migrations/0081_alter_user_last_active_date.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.4 on 2021-08-06 02:51 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0080_alter_shelfbook_options"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="last_active_date", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 21b6bbaac..cb6941c9b 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -111,7 +111,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): remote_id = fields.RemoteIdField(null=True, unique=True, activitypub_field="id") created_date = models.DateTimeField(auto_now_add=True) updated_date = models.DateTimeField(auto_now=True) - last_active_date = models.DateTimeField(auto_now=True) + last_active_date = models.DateTimeField(default=timezone.now) manually_approves_followers = fields.BooleanField(default=False) show_goal = models.BooleanField(default=True) discoverable = fields.BooleanField(default=False) From d126d7ba91caa8c0ec52dee20b0b22bedae81711 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 08:43:05 -0700 Subject: [PATCH 0116/1024] Disable comically inefficient book count comparisons Oops! Hopefully I can restore these in a way that doesn't break at even a moderate scale --- bookwyrm/suggested_users.py | 54 +++++++++++++------------- bookwyrm/tests/test_suggested_users.py | 6 +-- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 3a95ef7fe..de04b7e3c 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -19,7 +19,7 @@ class SuggestedUsers(RedisStore): def get_rank(self, obj): """get computed rank""" - return obj.mutuals + (1.0 - (1.0 / (obj.shared_books + 1))) + return obj.mutuals # + (1.0 - (1.0 / (obj.shared_books + 1))) def store_id(self, user): # pylint: disable=no-self-use """the key used to store this user's recs""" @@ -31,7 +31,7 @@ class SuggestedUsers(RedisStore): """calculate mutuals count and shared books count from rank""" return { "mutuals": math.floor(rank), - "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1, + # "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1, } def get_objects_for_store(self, store): @@ -95,7 +95,7 @@ class SuggestedUsers(RedisStore): logger.exception(err) continue user.mutuals = counts["mutuals"] - user.shared_books = counts["shared_books"] + # user.shared_books = counts["shared_books"] results.append(user) return results @@ -103,7 +103,9 @@ class SuggestedUsers(RedisStore): def get_annotated_users(viewer, *args, **kwargs): """Users, annotated with things they have in common""" return ( - models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs) + models.User.objects.filter( + discoverable=True, is_active=True, bookwyrm_user=True, *args, **kwargs + ) .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) .annotate( mutuals=Count( @@ -115,16 +117,16 @@ def get_annotated_users(viewer, *args, **kwargs): ), distinct=True, ), - shared_books=Count( - "shelfbook", - filter=Q( - ~Q(id=viewer.id), - shelfbook__book__parent_work__in=[ - s.book.parent_work for s in viewer.shelfbook_set.all() - ], - ), - distinct=True, - ), + # shared_books=Count( + # "shelfbook", + # filter=Q( + # ~Q(id=viewer.id), + # shelfbook__book__parent_work__in=[ + # s.book.parent_work for s in viewer.shelfbook_set.all() + # ], + # ), + # distinct=True, + # ), ) ) @@ -162,18 +164,18 @@ def update_suggestions_on_unfollow(sender, instance, **kwargs): rerank_user_task.delay(instance.user_object.id, update_only=False) -@receiver(signals.post_save, sender=models.ShelfBook) -@receiver(signals.post_delete, sender=models.ShelfBook) -# pylint: disable=unused-argument -def update_rank_on_shelving(sender, instance, *args, **kwargs): - """when a user shelves or unshelves a book, re-compute their rank""" - # if it's a local user, re-calculate who is rec'ed to them - if instance.user.local: - rerank_suggestions_task.delay(instance.user.id) - - # if the user is discoverable, update their rankings - if instance.user.discoverable: - rerank_user_task.delay(instance.user.id) +# @receiver(signals.post_save, sender=models.ShelfBook) +# @receiver(signals.post_delete, sender=models.ShelfBook) +# # pylint: disable=unused-argument +# def update_rank_on_shelving(sender, instance, *args, **kwargs): +# """when a user shelves or unshelves a book, re-compute their rank""" +# # if it's a local user, re-calculate who is rec'ed to them +# if instance.user.local: +# rerank_suggestions_task.delay(instance.user.id) +# +# # if the user is discoverable, update their rankings +# if instance.user.discoverable: +# rerank_user_task.delay(instance.user.id) @receiver(signals.post_save, sender=models.User) diff --git a/bookwyrm/tests/test_suggested_users.py b/bookwyrm/tests/test_suggested_users.py index 41e8911eb..7e4a9d00f 100644 --- a/bookwyrm/tests/test_suggested_users.py +++ b/bookwyrm/tests/test_suggested_users.py @@ -29,7 +29,7 @@ class SuggestedUsers(TestCase): Mock = namedtuple("AnnotatedUserMock", ("mutuals", "shared_books")) annotated_user_mock = Mock(3, 27) rank = suggested_users.get_rank(annotated_user_mock) - self.assertEqual(rank, 3.9642857142857144) + self.assertEqual(rank, 3) # 3.9642857142857144) def test_store_id(self, *_): """redis key generation""" @@ -42,7 +42,7 @@ class SuggestedUsers(TestCase): """reverse the rank computation to get the mutuals and shared books counts""" counts = suggested_users.get_counts_from_rank(3.9642857142857144) self.assertEqual(counts["mutuals"], 3) - self.assertEqual(counts["shared_books"], 27) + # self.assertEqual(counts["shared_books"], 27) def test_get_objects_for_store(self, *_): """list of people to follow for a given user""" @@ -126,7 +126,7 @@ class SuggestedUsers(TestCase): user_1_annotated = result.get(id=user_1.id) self.assertEqual(user_1_annotated.mutuals, 1) - self.assertEqual(user_1_annotated.shared_books, 1) + # self.assertEqual(user_1_annotated.shared_books, 1) def test_get_annotated_users_counts(self, *_): """correct counting for multiple shared attributed""" From 9030f0d08b5aabd729d5b13bfe5c0e54b9ee8e93 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 09:14:07 -0700 Subject: [PATCH 0117/1024] Bookwyrm user was already set --- bookwyrm/suggested_users.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index de04b7e3c..9c42d79d8 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -103,9 +103,7 @@ class SuggestedUsers(RedisStore): def get_annotated_users(viewer, *args, **kwargs): """Users, annotated with things they have in common""" return ( - models.User.objects.filter( - discoverable=True, is_active=True, bookwyrm_user=True, *args, **kwargs - ) + models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs) .exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer)) .annotate( mutuals=Count( From 134db20c57f4d8787aa9c237b311665a19e420aa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 09:40:01 -0700 Subject: [PATCH 0118/1024] Fixes directory view --- bookwyrm/views/directory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/directory.py b/bookwyrm/views/directory.py index 8a2e78dc2..8d893047a 100644 --- a/bookwyrm/views/directory.py +++ b/bookwyrm/views/directory.py @@ -28,7 +28,7 @@ class Directory(View): if sort == "recent": users = users.order_by("-last_active_date") else: - users = users.order_by("-mutuals", "-shared_books", "-last_active_date") + users = users.order_by("-mutuals", "-last_active_date") paginated = Paginator(users, 12) From 9804d4cf514585b66d286cc8d1d55a6b13f1eb3b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 10:19:38 -0700 Subject: [PATCH 0119/1024] Adds more book view tests --- bookwyrm/tests/views/test_book.py | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 3b6748523..6280f54ff 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -12,6 +12,7 @@ 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 django.utils import timezone from bookwyrm import forms, models, views from bookwyrm.activitypub import ActivitypubResponse @@ -52,6 +53,11 @@ class BookViews(TestCase): def test_book_page(self): """there are so many views, this just makes sure it LOADS""" view = views.Book.as_view() + models.ReadThrough.objects.create( + user=self.local_user, + book=self.book, + start_date=timezone.now(), + ) request = self.factory.get("") request.user = self.local_user with patch("bookwyrm.views.books.is_api_request") as is_api: @@ -67,6 +73,78 @@ class BookViews(TestCase): self.assertIsInstance(result, ActivitypubResponse) self.assertEqual(result.status_code, 200) + @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") + def test_book_page_statuses(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + + review = models.Review.objects.create( + user=self.local_user, + book=self.book, + content="hi", + ) + + comment = models.Comment.objects.create( + user=self.local_user, + book=self.book, + content="hi", + ) + + quote = models.Quotation.objects.create( + user=self.local_user, + book=self.book, + content="hi", + quote="wow", + ) + + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="review") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], review) + + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="comment") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], comment) + + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="quotation") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], quote) + + def test_book_page_invalid_id(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, 0) + self.assertEqual(result.status_code, 404) + + def test_book_page_work_id(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["book"], self.book) + def test_edit_book_page(self): """there are so many views, this just makes sure it LOADS""" view = views.EditBook.as_view() From 3abceb8563e3229e8d1ef5d34f89b8667ed917dc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 10:33:14 -0700 Subject: [PATCH 0120/1024] Templatetag test --- bookwyrm/tests/test_templatetags.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bookwyrm/tests/test_templatetags.py b/bookwyrm/tests/test_templatetags.py index 3c5d8b258..d75d368c1 100644 --- a/bookwyrm/tests/test_templatetags.py +++ b/bookwyrm/tests/test_templatetags.py @@ -175,3 +175,10 @@ class TemplateTags(TestCase): result = bookwyrm_tags.related_status(notification) self.assertIsInstance(result, models.Status) + + def test_get_next_shelf(self, *_): + """self progress helper""" + self.assertEqual(bookwyrm_tags.get_next_shelf("to-read"), "reading") + self.assertEqual(bookwyrm_tags.get_next_shelf("reading"), "read") + self.assertEqual(bookwyrm_tags.get_next_shelf("read"), "read") + self.assertEqual(bookwyrm_tags.get_next_shelf("blooooga"), "to-read") From 0d2622e4ffbb0436d94dbc81adf22bd6e4cb8d5a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:23:38 -0700 Subject: [PATCH 0121/1024] Tests login view --- bookwyrm/tests/views/test_authentication.py | 64 ++++++++++++++++++++- bookwyrm/views/authentication.py | 3 +- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index 10531f517..e2d67fbe1 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -8,7 +8,7 @@ from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory -from bookwyrm import models, views +from bookwyrm import forms, models, views from bookwyrm.settings import DOMAIN @@ -22,7 +22,7 @@ class AuthenticationViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): self.local_user = models.User.objects.create_user( - "mouse@local.com", + "mouse@your.domain.here", "mouse@mouse.com", "password", local=True, @@ -49,6 +49,66 @@ class AuthenticationViews(TestCase): self.assertEqual(result.url, "/") self.assertEqual(result.status_code, 302) + def test_login_post_localname(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse@mouse.com" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_username(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse@your.domain.here" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_email(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_invalid_credentials(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse" + form.data["password"] = "passsword1" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual( + result.context_data["login_form"].non_field_errors, + "Username or password are incorrect", + ) + def test_register(self, _): """create a user""" view = views.Register.as_view() diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 003e94b09..6598aef2a 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator +from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import csrf_exempt from django.views import View @@ -54,7 +55,7 @@ class Login(View): return redirect(request.GET.get("next", "/")) # login errors - login_form.non_field_errors = "Username or password are incorrect" + login_form.non_field_errors = _("Username or password are incorrect") register_form = forms.RegisterForm() data = {"login_form": login_form, "register_form": register_form} return TemplateResponse(request, "login.html", data) From 568e30230a58d5d1263af36633b304c9dcf5a72b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:43:55 -0700 Subject: [PATCH 0122/1024] Adds start import view test --- bookwyrm/tests/views/test_import.py | 26 ++++++++++++++++++++++++-- locale/de_DE/LC_MESSAGES/django.po | 6 +++++- locale/en_US/LC_MESSAGES/django.po | 6 +++++- locale/es/LC_MESSAGES/django.po | 6 +++++- locale/fr_FR/LC_MESSAGES/django.po | 6 +++++- locale/zh_Hans/LC_MESSAGES/django.po | 6 +++++- locale/zh_Hant/LC_MESSAGES/django.po | 6 +++++- 7 files changed, 54 insertions(+), 8 deletions(-) diff --git a/bookwyrm/tests/views/test_import.py b/bookwyrm/tests/views/test_import.py index 13c0ef5d2..d9d67d568 100644 --- a/bookwyrm/tests/views/test_import.py +++ b/bookwyrm/tests/views/test_import.py @@ -1,11 +1,12 @@ """ test for app action functionality """ +import pathlib from unittest.mock import patch +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 models -from bookwyrm import views +from bookwyrm import forms, models, views class ImportViews(TestCase): @@ -47,6 +48,27 @@ class ImportViews(TestCase): result.render() self.assertEqual(result.status_code, 200) + def test_start_import(self): + """retry failed items""" + view = views.Import.as_view() + form = forms.ImportForm() + form.data["source"] = "LibraryThing" + form.data["privacy"] = "public" + form.data["include_reviews"] = False + csv_file = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv") + form.data["csv_file"] = SimpleUploadedFile( + csv_file, open(csv_file, "rb").read(), content_type="text/csv" + ) + + request = self.factory.post("", form.data) + request.user = self.local_user + + with patch("bookwyrm.importers.Importer.start_import"): + view(request) + job = models.ImportJob.objects.get() + self.assertFalse(job.include_reviews) + self.assertEqual(job.privacy, "public") + def test_retry_import(self): """retry failed items""" view = views.ImportStatus.as_view() diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index b047f0310..140f91dcc 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -3295,6 +3295,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 #, fuzzy #| msgid "Email address:" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index 153d8b9a1..ab56046ee 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -2991,6 +2991,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "" diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 5bae4d7e2..dbf7540c7 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3036,6 +3036,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "No un archivo csv válido" diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index 399e40563..b4405df5a 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -3015,6 +3015,10 @@ msgstr "Ce fichier dépasse la taille limite : 10 Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "Fichier CSV non valide" diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index d9921655e..471de85d0 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -2992,6 +2992,10 @@ msgstr "文件超过了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "不是有效的 csv 文件" diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 5ce42251b..40b12995b 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -3011,6 +3011,10 @@ msgstr "檔案超過了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "不是有效的 csv 檔案" From 3082c4ce5c7d7dafa5016cef1a463e1e94412aaa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:55:20 -0700 Subject: [PATCH 0123/1024] Tests invite create view --- bookwyrm/tests/views/test_invite.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bookwyrm/tests/views/test_invite.py b/bookwyrm/tests/views/test_invite.py index 1eaf57c03..6ad464208 100644 --- a/bookwyrm/tests/views/test_invite.py +++ b/bookwyrm/tests/views/test_invite.py @@ -52,6 +52,26 @@ class InviteViews(TestCase): result.render() self.assertEqual(result.status_code, 200) + def test_manage_invites_post(self): + """there are so many views, this just makes sure it LOADS""" + view = views.ManageInvites.as_view() + form = forms.CreateInviteForm() + form.data["use_limit"] = 3 + form.data["expiry"] = "" + request = self.factory.post("", form.data) + request.user = self.local_user + request.user.is_superuser = True + + result = view(request) + + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + + invite = models.SiteInvite.objects.get() + self.assertEqual(invite.use_limit, 3) + self.assertIsNone(invite.expiry) + def test_invite_request(self): """request to join a server""" form = forms.InviteRequestForm() From 3e2f1806e9a3d490599665afb442a10ebd8acc5d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 14:42:18 -0700 Subject: [PATCH 0124/1024] Adds email confirmation code field --- .../migrations/0082_auto_20210806_2141.py | 51 +++++++++++++++++++ bookwyrm/models/base_model.py | 8 +++ bookwyrm/models/site.py | 9 +--- bookwyrm/models/user.py | 3 +- 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 bookwyrm/migrations/0082_auto_20210806_2141.py diff --git a/bookwyrm/migrations/0082_auto_20210806_2141.py b/bookwyrm/migrations/0082_auto_20210806_2141.py new file mode 100644 index 000000000..76c8c9628 --- /dev/null +++ b/bookwyrm/migrations/0082_auto_20210806_2141.py @@ -0,0 +1,51 @@ +# Generated by Django 3.2.4 on 2021-08-06 21:41 + +import bookwyrm.models.base_model +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0081_alter_user_last_active_date"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="confirmation_code", + field=models.CharField( + default=bookwyrm.models.base_model.new_access_code, max_length=32 + ), + ), + migrations.AlterField( + model_name="connector", + name="deactivation_reason", + field=models.CharField( + blank=True, + choices=[ + ("pending", "Pending"), + ("self_deletion", "Self Deletion"), + ("moderator_deletion", "Moderator Deletion"), + ("domain_block", "Domain Block"), + ], + max_length=255, + null=True, + ), + ), + migrations.AlterField( + model_name="user", + name="deactivation_reason", + field=models.CharField( + blank=True, + choices=[ + ("pending", "Pending"), + ("self_deletion", "Self Deletion"), + ("moderator_deletion", "Moderator Deletion"), + ("domain_block", "Domain Block"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index 2cb7c0365..5b55ea50f 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -1,4 +1,6 @@ """ base model with default fields """ +import base64 +from Crypto import Random from django.db import models from django.dispatch import receiver @@ -9,6 +11,7 @@ from .fields import RemoteIdField DeactivationReason = models.TextChoices( "DeactivationReason", [ + "pending", "self_deletion", "moderator_deletion", "domain_block", @@ -16,6 +19,11 @@ DeactivationReason = models.TextChoices( ) +def new_access_code(): + """the identifier for a user invite""" + return base64.b32encode(Random.get_random_bytes(5)).decode("ascii") + + class BookWyrmModel(models.Model): """shared fields""" diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index 872f6b454..fdc068664 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -1,8 +1,6 @@ """ the particulars for this instance of BookWyrm """ -import base64 import datetime -from Crypto import Random from django.db import models, IntegrityError from django.dispatch import receiver from django.utils import timezone @@ -10,7 +8,7 @@ from model_utils import FieldTracker from bookwyrm.preview_images import generate_site_preview_image_task from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES -from .base_model import BookWyrmModel +from .base_model import BookWyrmModel, new_access_code from .user import User @@ -61,11 +59,6 @@ class SiteSettings(models.Model): return default_settings -def new_access_code(): - """the identifier for a user invite""" - return base64.b32encode(Random.get_random_bytes(5)).decode("ascii") - - class SiteInvite(models.Model): """gives someone access to create an account on the instance""" diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index cb6941c9b..08bd87b3c 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -22,7 +22,7 @@ from bookwyrm.signatures import create_key_pair from bookwyrm.tasks import app from bookwyrm.utils import regex from .activitypub_mixin import OrderedCollectionPageMixin, ActivitypubMixin -from .base_model import BookWyrmModel, DeactivationReason +from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review @@ -123,6 +123,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): deactivation_reason = models.CharField( max_length=255, choices=DeactivationReason.choices, null=True, blank=True ) + confirmation_code = models.CharField(max_length=32, default=new_access_code) name_field = "username" property_fields = [("following_link", "following")] From 247a7f74896e91ba09c6ae3e9467bb332fa8eee9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 15:38:37 -0700 Subject: [PATCH 0125/1024] Email confirmation email --- .env.dev.example | 3 +++ .env.prod.example | 3 +++ bookwyrm/emailing.py | 7 +++++++ bookwyrm/models/user.py | 16 +++++++++++++--- bookwyrm/settings.py | 3 +++ .../templates/email/confirm/html_content.html | 14 ++++++++++++++ bookwyrm/templates/email/confirm/subject.html | 4 ++++ .../templates/email/confirm/text_content.html | 11 +++++++++++ bookwyrm/views/authentication.py | 15 ++++++++++++--- bookwyrm/views/site.py | 2 ++ 10 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 bookwyrm/templates/email/confirm/html_content.html create mode 100644 bookwyrm/templates/email/confirm/subject.html create mode 100644 bookwyrm/templates/email/confirm/text_content.html diff --git a/.env.dev.example b/.env.dev.example index f42aaaaec..a74e7bb36 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -36,6 +36,9 @@ FLOWER_PORT=8888 #FLOWER_USER=mouse #FLOWER_PASSWORD=changeme +# make users confirm their email addresses after registration +CONFIRM_EMAIL=false + EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/.env.prod.example b/.env.prod.example index 5115469ca..c5edb55ec 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -36,6 +36,9 @@ FLOWER_PORT=8888 FLOWER_USER=mouse FLOWER_PASSWORD=changeme +# make users confirm their email addresses after registration +CONFIRM_EMAIL=true + EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index 657310b05..516d64c93 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -23,6 +23,13 @@ def email_data(): } +def email_confirmation_email(user): + """newly registered users confirm email address""" + data = email_data() + data["confirmation_code"] = user.confirmation_code + data["confirmation_link"] = user.confirmation_link + send_email.delay(user.email, *format_email("confirm_email", data)) + def invite_email(invite_request): """send out an invite code""" data = email_data() diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 08bd87b3c..94b7b41e1 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -17,7 +17,7 @@ from bookwyrm.connectors import get_data, ConnectorException from bookwyrm.models.shelf import Shelf from bookwyrm.models.status import Status, Review from bookwyrm.preview_images import generate_user_preview_image_task -from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES +from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, USE_HTTPS from bookwyrm.signatures import create_key_pair from bookwyrm.tasks import app from bookwyrm.utils import regex @@ -26,6 +26,10 @@ from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review +def site_link(): + """helper for generating links to the site""" + protocol = "https" if USE_HTTPS else "http" + return f"{protocol}://{DOMAIN}" class User(OrderedCollectionPageMixin, AbstractUser): """a user who wants to read books""" @@ -129,6 +133,12 @@ class User(OrderedCollectionPageMixin, AbstractUser): property_fields = [("following_link", "following")] field_tracker = FieldTracker(fields=["name", "avatar"]) + @property + def confirmation_link(self): + """helper for generating confirmation links""" + link = site_link() + return f"{link}/confirm-email/{self.confirmation_code}" + @property def following_link(self): """just how to find out the following info""" @@ -260,9 +270,9 @@ class User(OrderedCollectionPageMixin, AbstractUser): return # populate fields for local users - self.remote_id = "https://%s/user/%s" % (DOMAIN, self.localname) + self.remote_id = "%s/user/%s" % (site_link(), self.localname) self.inbox = "%s/inbox" % self.remote_id - self.shared_inbox = "https://%s/inbox" % DOMAIN + self.shared_inbox = "%s/inbox" % site_link() self.outbox = "%s/outbox" % self.remote_id # an id needs to be set before we can proceed with related models diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 180191d98..130889ac2 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -24,6 +24,9 @@ CELERY_ACCEPT_CONTENT = ["application/json"] CELERY_TASK_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json" +# make users confirm their email addresses after registration +CONFIRM_EMAIL = env("CONFIRM_EMAIL", True) + # email EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") EMAIL_HOST = env("EMAIL_HOST") diff --git a/bookwyrm/templates/email/confirm/html_content.html b/bookwyrm/templates/email/confirm/html_content.html new file mode 100644 index 000000000..b47642af7 --- /dev/null +++ b/bookwyrm/templates/email/confirm/html_content.html @@ -0,0 +1,14 @@ +{% extends 'email/html_layout.html' %} +{% load i18n %} + +{% block content %} +

+{% blocktrans trimmed %} +One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below: +{% endblocktrans %} +

+ +{% trans "Confirm Email" as text %} +{% include 'email/snippets/action.html' with path=confirmation_link text=text %} + +{% endblock %} diff --git a/bookwyrm/templates/email/confirm/subject.html b/bookwyrm/templates/email/confirm/subject.html new file mode 100644 index 000000000..b81a5a83f --- /dev/null +++ b/bookwyrm/templates/email/confirm/subject.html @@ -0,0 +1,4 @@ +{% load i18n %} +{% blocktrans trimmed %} +Please confirm your email +{% endblocktrans %} diff --git a/bookwyrm/templates/email/confirm/text_content.html b/bookwyrm/templates/email/confirm/text_content.html new file mode 100644 index 000000000..e3d739383 --- /dev/null +++ b/bookwyrm/templates/email/confirm/text_content.html @@ -0,0 +1,11 @@ +{% extends 'email/text_layout.html' %} +{% load i18n %} +{% block content %} +{% blocktrans trimmed %} +One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below: +{% endblocktrans %} + +{{ confirmation_link }} + + +{% endblock %} diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 003e94b09..43b4bb373 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -9,8 +9,8 @@ from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views import View -from bookwyrm import forms, models -from bookwyrm.settings import DOMAIN +from bookwyrm import emailing, forms, models +from bookwyrm.settings import DOMAIN, CONFIRM_EMAIL # pylint: disable= no-self-use @@ -104,13 +104,22 @@ class Register(View): username = "%s@%s" % (localname, DOMAIN) user = models.User.objects.create_user( - username, email, password, localname=localname, local=True + username, + email, + password, + localname=localname, + local=True, + is_active=not CONFIRM_EMAIL, ) if invite: invite.times_used += 1 invite.invitees.add(user) invite.save() + if CONFIRM_EMAIL: + emailing.email_confirmation_email(user) + return redirect("confirm-email") + login(request, user) return redirect("get-started-profile") diff --git a/bookwyrm/views/site.py b/bookwyrm/views/site.py index 46bdf7226..42e8a6dd5 100644 --- a/bookwyrm/views/site.py +++ b/bookwyrm/views/site.py @@ -46,4 +46,6 @@ def email_preview(request): data["text_content_path"] = "email/{}/text_content.html".format(template) data["reset_link"] = "https://example.com/link" data["invite_link"] = "https://example.com/link" + data["confirmation_link"] = "https://example.com/link" + data["confirmation_code"] = "AKJHKDGKJSDFG" return TemplateResponse(request, "email/preview.html", data) From 5926224d7e5784be753da402822ff8e5a9a879f0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 16:24:57 -0700 Subject: [PATCH 0126/1024] Confirm email views --- .env.dev.example | 3 - .env.prod.example | 3 - bookwyrm/emailing.py | 1 + ...806_2141.py => 0082_auto_20210806_2324.py} | 7 +- bookwyrm/models/site.py | 1 + bookwyrm/models/user.py | 6 +- bookwyrm/settings.py | 3 - bookwyrm/templates/confirm_email.html | 1 + bookwyrm/urls.py | 7 ++ bookwyrm/views/__init__.py | 1 + bookwyrm/views/authentication.py | 73 +++++++++++++++---- 11 files changed, 78 insertions(+), 28 deletions(-) rename bookwyrm/migrations/{0082_auto_20210806_2141.py => 0082_auto_20210806_2324.py} (87%) create mode 100644 bookwyrm/templates/confirm_email.html diff --git a/.env.dev.example b/.env.dev.example index a74e7bb36..f42aaaaec 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -36,9 +36,6 @@ FLOWER_PORT=8888 #FLOWER_USER=mouse #FLOWER_PASSWORD=changeme -# make users confirm their email addresses after registration -CONFIRM_EMAIL=false - EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/.env.prod.example b/.env.prod.example index c5edb55ec..5115469ca 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -36,9 +36,6 @@ FLOWER_PORT=8888 FLOWER_USER=mouse FLOWER_PASSWORD=changeme -# make users confirm their email addresses after registration -CONFIRM_EMAIL=true - EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index 516d64c93..cf46baf33 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -30,6 +30,7 @@ def email_confirmation_email(user): data["confirmation_link"] = user.confirmation_link send_email.delay(user.email, *format_email("confirm_email", data)) + def invite_email(invite_request): """send out an invite code""" data = email_data() diff --git a/bookwyrm/migrations/0082_auto_20210806_2141.py b/bookwyrm/migrations/0082_auto_20210806_2324.py similarity index 87% rename from bookwyrm/migrations/0082_auto_20210806_2141.py rename to bookwyrm/migrations/0082_auto_20210806_2324.py index 76c8c9628..ab0aa158b 100644 --- a/bookwyrm/migrations/0082_auto_20210806_2141.py +++ b/bookwyrm/migrations/0082_auto_20210806_2324.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.4 on 2021-08-06 21:41 +# Generated by Django 3.2.4 on 2021-08-06 23:24 import bookwyrm.models.base_model from django.db import migrations, models @@ -11,6 +11,11 @@ class Migration(migrations.Migration): ] operations = [ + migrations.AddField( + model_name="sitesettings", + name="require_confirm_email", + field=models.BooleanField(default=True), + ), migrations.AddField( model_name="user", name="confirmation_code", diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index fdc068664..ef3f7c3ca 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -31,6 +31,7 @@ class SiteSettings(models.Model): # registration allow_registration = models.BooleanField(default=True) allow_invite_requests = models.BooleanField(default=True) + require_confirm_email = models.BooleanField(default=True) # images logo = models.ImageField(upload_to="logos/", null=True, blank=True) diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 94b7b41e1..e10bcd293 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -26,11 +26,13 @@ from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review + def site_link(): """helper for generating links to the site""" protocol = "https" if USE_HTTPS else "http" return f"{protocol}://{DOMAIN}" + class User(OrderedCollectionPageMixin, AbstractUser): """a user who wants to read books""" @@ -218,7 +220,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): self.following.order_by("-updated_date").all(), remote_id=remote_id, id_only=True, - **kwargs + **kwargs, ) def to_followers_activity(self, **kwargs): @@ -228,7 +230,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): self.followers.order_by("-updated_date").all(), remote_id=remote_id, id_only=True, - **kwargs + **kwargs, ) def to_activity(self, **kwargs): diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 130889ac2..180191d98 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -24,9 +24,6 @@ CELERY_ACCEPT_CONTENT = ["application/json"] CELERY_TASK_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json" -# make users confirm their email addresses after registration -CONFIRM_EMAIL = env("CONFIRM_EMAIL", True) - # email EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") EMAIL_HOST = env("EMAIL_HOST") diff --git a/bookwyrm/templates/confirm_email.html b/bookwyrm/templates/confirm_email.html new file mode 100644 index 000000000..ac5b92825 --- /dev/null +++ b/bookwyrm/templates/confirm_email.html @@ -0,0 +1 @@ +{% extends "layout.html" %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index d3e2dad1a..e7036feb9 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -46,7 +46,14 @@ urlpatterns = [ re_path("^api/updates/stream/(?P[a-z]+)/?$", views.get_unread_status_count), # authentication re_path(r"^login/?$", views.Login.as_view(), name="login"), + re_path(r"^login/(?Pconfirmed)?$", views.Login.as_view(), name="login"), re_path(r"^register/?$", views.Register.as_view()), + re_path(r"confirm-email/?$", views.ConfirmEmail.as_view(), name="confirm-email"), + re_path( + r"confirm-email/(?P[A-Za-z0-9]+)/?$", + views.ConfirmEmailCode.as_view(), + name="confirm-email-code", + ), re_path(r"^logout/?$", views.Logout.as_view(), name="logout"), re_path( r"^password-reset/?$", diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 41bb64e54..112271a76 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -1,6 +1,7 @@ """ make sure all our nice views are available """ from .announcements import Announcements, Announcement, delete_announcement from .authentication import Login, Register, Logout +from .authentication import ConfirmEmail, ConfirmEmailCode from .author import Author, EditAuthor from .block import Block, unblock from .books import Book, EditBook, ConfirmEditBook, Editions diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 43b4bb373..edf960cc1 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -10,20 +10,21 @@ from django.views.decorators.csrf import csrf_exempt from django.views import View from bookwyrm import emailing, forms, models -from bookwyrm.settings import DOMAIN, CONFIRM_EMAIL +from bookwyrm.settings import DOMAIN -# pylint: disable= no-self-use +# pylint: disable=no-self-use @method_decorator(csrf_exempt, name="dispatch") class Login(View): """authenticate an existing user""" - def get(self, request): + def get(self, request, confirmed=None): """login page""" if request.user.is_authenticated: return redirect("/") - # sene user to the login page + # send user to the login page data = { + "show_confirmed_email": confirmed, "login_form": forms.LoginForm(), "register_form": forms.RegisterForm(), } @@ -37,14 +38,15 @@ class Login(View): localname = login_form.data["localname"] if "@" in localname: # looks like an email address to me - email = localname try: - username = models.User.objects.get(email=email) + username = models.User.objects.get(email=localname).username except models.User.DoesNotExist: # maybe it's a full username? username = localname else: username = "%s@%s" % (localname, DOMAIN) password = login_form.data["password"] + + # perform authentication user = authenticate(request, username=username, password=password) if user is not None: # successful login @@ -53,6 +55,12 @@ class Login(View): user.save(broadcast=False, update_fields=["last_active_date"]) return redirect(request.GET.get("next", "/")) + # maybe the user is pending email confirmation + if models.User.objects.filter( + username=username, is_active=False, deactivation_reason="pending" + ).exists(): + return redirect("confirm-email") + # login errors login_form.non_field_errors = "Username or password are incorrect" register_form = forms.RegisterForm() @@ -60,12 +68,23 @@ class Login(View): return TemplateResponse(request, "login.html", data) +@method_decorator(login_required, name="dispatch") +class Logout(View): + """log out""" + + def get(self, request): + """done with this place! outa here!""" + logout(request) + return redirect("/") + + class Register(View): """register a user""" def post(self, request): """join the server""" - if not models.SiteSettings.get().allow_registration: + settings = models.SiteSettings.get() + if not settings.allow_registration: invite_code = request.POST.get("invite_code") if not invite_code: @@ -109,14 +128,15 @@ class Register(View): password, localname=localname, local=True, - is_active=not CONFIRM_EMAIL, + deactivation_reason="pending" if settings.require_confirm_email else None, + is_active=not settings.require_confirm_email, ) if invite: invite.times_used += 1 invite.invitees.add(user) invite.save() - if CONFIRM_EMAIL: + if settings.require_confirm_email: emailing.email_confirmation_email(user) return redirect("confirm-email") @@ -124,11 +144,32 @@ class Register(View): return redirect("get-started-profile") -@method_decorator(login_required, name="dispatch") -class Logout(View): - """log out""" +class ConfirmEmail(View): + """enter code to confirm email address""" - def get(self, request): - """done with this place! outa here!""" - logout(request) - return redirect("/") + def get(self, request): # pylint: disable=unused-argument + """you need a code! keep looking""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + return TemplateResponse(request, "confirm_email.html") + + +class ConfirmEmailCode(View): + """confirm email address""" + + def get(self, request, code): # pylint: disable=unused-argument + """you got the code! good work""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + # look up the user associated with this code + user = get_object_or_404(models.User, confirmation_code=code) + # update the user + user.is_active = True + user.deactivation_reason = None + user.save(broadcast=False, update_fields=["is_active", "deactivation_reason"]) + # direct the user to log in + return redirect("login", confirmed="confirmed") From 1ad057d89d5e99fc4eff546cb1abe93289f53b9a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:23:44 -0700 Subject: [PATCH 0127/1024] Confirmation templates --- bookwyrm/emailing.py | 2 +- bookwyrm/templates/confirm_email.html | 1 - .../confirm_email/confirm_email.html | 44 +++++++++++++++++++ .../templates/confirm_email/resend_form.html | 19 ++++++++ bookwyrm/templates/settings/site.html | 7 +++ bookwyrm/views/authentication.py | 34 ++++++++------ 6 files changed, 92 insertions(+), 15 deletions(-) delete mode 100644 bookwyrm/templates/confirm_email.html create mode 100644 bookwyrm/templates/confirm_email/confirm_email.html create mode 100644 bookwyrm/templates/confirm_email/resend_form.html diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index cf46baf33..fff3985ef 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -28,7 +28,7 @@ def email_confirmation_email(user): data = email_data() data["confirmation_code"] = user.confirmation_code data["confirmation_link"] = user.confirmation_link - send_email.delay(user.email, *format_email("confirm_email", data)) + send_email.delay(user.email, *format_email("confirm", data)) def invite_email(invite_request): diff --git a/bookwyrm/templates/confirm_email.html b/bookwyrm/templates/confirm_email.html deleted file mode 100644 index ac5b92825..000000000 --- a/bookwyrm/templates/confirm_email.html +++ /dev/null @@ -1 +0,0 @@ -{% extends "layout.html" %} diff --git a/bookwyrm/templates/confirm_email/confirm_email.html b/bookwyrm/templates/confirm_email/confirm_email.html new file mode 100644 index 000000000..85ca2bb1b --- /dev/null +++ b/bookwyrm/templates/confirm_email/confirm_email.html @@ -0,0 +1,44 @@ +{% extends "layout.html" %} +{% load i18n %} + +{% block title %}{% trans "Confirm email" %}{% endblock %} + +{% block content %} +

{% trans "Confirm your email address" %}

+ +
+
+
+
+

{% trans "A confirmation code has been sent to the email address you used to register your account." %}

+ {% if not valid %} +

{% trans "Sorry! We couldn't find that code." %}

+ {% endif %} + + {% csrf_token %} + +
+
+ +
+
+ +
+
+ +
+ +
+ {% trans "Can't find your code?" as button_text %} + {% include "snippets/toggle/open_button.html" with text=button_text controls_text="resend-form" focus="resend-form-header" %} + {% include "confirm_email/resend_form.html" with controls_text="resend-form" %} +
+
+
+
+
+ {% include 'snippets/about.html' %} +
+
+
+{% endblock %} diff --git a/bookwyrm/templates/confirm_email/resend_form.html b/bookwyrm/templates/confirm_email/resend_form.html new file mode 100644 index 000000000..00a89403f --- /dev/null +++ b/bookwyrm/templates/confirm_email/resend_form.html @@ -0,0 +1,19 @@ +{% extends "components/inline_form.html" %} +{% load i18n %} +{% block header %} +{% trans "Resend confirmation link" %} +{% endblock %} + +{% block form %} +
+
+ +
+ +
+
+
+ +
+
+{% endblock %} diff --git a/bookwyrm/templates/settings/site.html b/bookwyrm/templates/settings/site.html index d36371a41..f64b529ad 100644 --- a/bookwyrm/templates/settings/site.html +++ b/bookwyrm/templates/settings/site.html @@ -91,6 +91,13 @@ {% trans "Allow invite requests" %}
+
+ +

{% trans "(Recommended if registration is open)" %}

+
{{ site_form.registration_closed_text }} diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index edf960cc1..dedcf408a 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -144,18 +144,6 @@ class Register(View): return redirect("get-started-profile") -class ConfirmEmail(View): - """enter code to confirm email address""" - - def get(self, request): # pylint: disable=unused-argument - """you need a code! keep looking""" - settings = models.SiteSettings.get() - if request.user.is_authenticated or not settings.require_confirm_email: - return redirect("/") - - return TemplateResponse(request, "confirm_email.html") - - class ConfirmEmailCode(View): """confirm email address""" @@ -166,10 +154,30 @@ class ConfirmEmailCode(View): return redirect("/") # look up the user associated with this code - user = get_object_or_404(models.User, confirmation_code=code) + try: + user = models.User.objects.get(confirmation_code=code) + except models.User.DoesNotExist: + return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": False}) # update the user user.is_active = True user.deactivation_reason = None user.save(broadcast=False, update_fields=["is_active", "deactivation_reason"]) # direct the user to log in return redirect("login", confirmed="confirmed") + + +class ConfirmEmail(View): + """enter code to confirm email address""" + + def get(self, request): # pylint: disable=unused-argument + """you need a code! keep looking""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": True}) + + def post(self, request): + """same as clicking the link""" + code = request.POST.get("code") + return ConfirmEmailCode().get(request, code) From 9077516fa14c9d64c06d1a81e0c2185d63d74229 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:39:22 -0700 Subject: [PATCH 0128/1024] Resend links --- .../confirm_email/confirm_email.html | 2 +- .../templates/confirm_email/resend_form.html | 5 +++-- bookwyrm/templates/login.html | 5 +++++ bookwyrm/urls.py | 1 + bookwyrm/views/__init__.py | 2 +- bookwyrm/views/authentication.py | 22 +++++++++++++++++-- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/bookwyrm/templates/confirm_email/confirm_email.html b/bookwyrm/templates/confirm_email/confirm_email.html index 85ca2bb1b..6c9eda5ee 100644 --- a/bookwyrm/templates/confirm_email/confirm_email.html +++ b/bookwyrm/templates/confirm_email/confirm_email.html @@ -19,7 +19,7 @@
- +
diff --git a/bookwyrm/templates/confirm_email/resend_form.html b/bookwyrm/templates/confirm_email/resend_form.html index 00a89403f..7c0c10980 100644 --- a/bookwyrm/templates/confirm_email/resend_form.html +++ b/bookwyrm/templates/confirm_email/resend_form.html @@ -5,11 +5,12 @@ {% endblock %} {% block form %} -
+ + {% csrf_token %}
- +
diff --git a/bookwyrm/templates/login.html b/bookwyrm/templates/login.html index e3d0133cf..19c103eac 100644 --- a/bookwyrm/templates/login.html +++ b/bookwyrm/templates/login.html @@ -11,8 +11,13 @@ {% if login_form.non_field_errors %}

{{ login_form.non_field_errors }}

{% endif %} + + {% if show_confirmed_email %} +

{% trans "Success! Email address confirmed." %}

+ {% endif %} {% csrf_token %} + {% if show_confirmed_email %}{% endif %}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index e7036feb9..eb8491a94 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -54,6 +54,7 @@ urlpatterns = [ views.ConfirmEmailCode.as_view(), name="confirm-email-code", ), + re_path(r"resend-link", views.resend_link, name="resend-link"), re_path(r"^logout/?$", views.Logout.as_view(), name="logout"), re_path( r"^password-reset/?$", diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 112271a76..eccb7f5e5 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -1,7 +1,7 @@ """ make sure all our nice views are available """ from .announcements import Announcements, Announcement, delete_announcement from .authentication import Login, Register, Logout -from .authentication import ConfirmEmail, ConfirmEmailCode +from .authentication import ConfirmEmail, ConfirmEmailCode, resend_link from .author import Author, EditAuthor from .block import Block, unblock from .books import Book, EditBook, ConfirmEditBook, Editions diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index dedcf408a..f81be8d15 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -7,6 +7,7 @@ from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.http import require_POST from django.views import View from bookwyrm import emailing, forms, models @@ -53,6 +54,8 @@ class Login(View): login(request, user) user.last_active_date = timezone.now() user.save(broadcast=False, update_fields=["last_active_date"]) + if request.POST.get("first_login"): + return redirect("get-started-profile") return redirect(request.GET.get("next", "/")) # maybe the user is pending email confirmation @@ -157,7 +160,9 @@ class ConfirmEmailCode(View): try: user = models.User.objects.get(confirmation_code=code) except models.User.DoesNotExist: - return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": False}) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": False} + ) # update the user user.is_active = True user.deactivation_reason = None @@ -175,9 +180,22 @@ class ConfirmEmail(View): if request.user.is_authenticated or not settings.require_confirm_email: return redirect("/") - return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": True}) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": True} + ) def post(self, request): """same as clicking the link""" code = request.POST.get("code") return ConfirmEmailCode().get(request, code) + + +@require_POST +def resend_link(request): + """resend confirmation link""" + email = request.POST.get("email") + user = get_object_or_404(models.User, email=email) + emailing.email_confirmation_email(user) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": True} + ) From cec69430692ee29075fab8d45ced4ae9e497abc4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:43:50 -0700 Subject: [PATCH 0129/1024] Adds missing mock --- bookwyrm/tests/views/test_book.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 6280f54ff..c5d86a12d 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -74,7 +74,8 @@ class BookViews(TestCase): self.assertEqual(result.status_code, 200) @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") - def test_book_page_statuses(self, _): + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_book_page_statuses(self, *_): """there are so many views, this just makes sure it LOADS""" view = views.Book.as_view() From 98a98f8e691f533edaef220877e145207a7661b2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:13:51 -0700 Subject: [PATCH 0130/1024] Updates test env --- .github/workflows/django-tests.yml | 1 + bookwyrm/tests/views/test_authentication.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml index 03147744a..038751935 100644 --- a/.github/workflows/django-tests.yml +++ b/.github/workflows/django-tests.yml @@ -36,6 +36,7 @@ jobs: env: SECRET_KEY: beepbeep DEBUG: false + USE_HTTPS: true DOMAIN: your.domain.here BOOKWYRM_DATABASE_BACKEND: postgres MEDIA_ROOT: images/ diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index e2d67fbe1..bbafe7bd5 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -31,7 +31,9 @@ class AuthenticationViews(TestCase): self.anonymous_user = AnonymousUser self.anonymous_user.is_authenticated = False - self.settings = models.SiteSettings.objects.create(id=1) + self.settings = models.SiteSettings.objects.create( + id=1, require_email_confirmation=False + ) def test_login_get(self, _): """there are so many views, this just makes sure it LOADS""" From a3d5a0347770e6eb6621aed5a362a5d6abd0fe28 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:47:25 -0700 Subject: [PATCH 0131/1024] Updates locales --- locale/de_DE/LC_MESSAGES/django.po | 121 +++++++++++++++++++------- locale/en_US/LC_MESSAGES/django.po | 108 +++++++++++++++++------ locale/es/LC_MESSAGES/django.po | 121 ++++++++++++++++++++------ locale/fr_FR/LC_MESSAGES/django.po | 123 ++++++++++++++++++++------- locale/zh_Hans/LC_MESSAGES/django.po | 118 +++++++++++++++++++------ locale/zh_Hant/LC_MESSAGES/django.po | 118 +++++++++++++++++++------ 6 files changed, 552 insertions(+), 157 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 140f91dcc..4906082a5 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -306,7 +306,7 @@ msgstr "" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -739,6 +739,58 @@ msgstr "Schließen" msgid "Compose status" msgstr "Status teilen" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Bestätigen" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "E-Mail Adresse" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Passwort bestätigen:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Absenden" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "E-Mail Adresse" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +msgid "Resend link" +msgstr "" + #: bookwyrm/templates/directory/community_filter.html:5 #, fuzzy #| msgid "Comment" @@ -882,7 +934,7 @@ msgid "Join %(name)s" msgstr "Tritt %(name)s bei" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Diese Instanz ist geschlossen" @@ -894,22 +946,26 @@ msgstr "" msgid "Request an Invitation" msgstr "" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "E-Mail Adresse" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Absenden" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Dein Account" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Bestätigen" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1342,7 +1398,7 @@ msgid "Imported" msgstr "Importiert" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Erstelle einen Account" @@ -1412,7 +1468,7 @@ msgid "Notifications" msgstr "Benachrichtigungen" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" @@ -1421,12 +1477,12 @@ msgstr "" msgid "password" msgstr "Passwort" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "Passwort vergessen?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Anmelden" @@ -1619,16 +1675,20 @@ msgstr "Deine Listen" msgid "Login" msgstr "" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Passwort:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Kontaktiere für eine Einladung eine*n Admin" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "Mehr über diese Seite" @@ -2554,7 +2614,15 @@ msgstr "Registrierungen erlauben" msgid "Allow invite requests" msgstr "Folgeanfragen" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Registrierungen geschlossen text" @@ -3295,7 +3363,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3375,11 +3443,6 @@ msgstr "" #~ msgid "Enter a valid integer." #~ msgstr "E-Mail Adresse" -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Enter a valid email address." -#~ msgstr "E-Mail Adresse" - #, fuzzy #~| msgid "Email address:" #~ msgid "Enter a valid IPv4 address." diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index ab56046ee..e8e3b0b31 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -282,7 +282,7 @@ msgstr "" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -680,6 +680,52 @@ msgstr "" msgid "Compose status" msgstr "" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +msgid "Confirm email" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +msgid "Confirm your email address" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +msgid "Confirmation code:" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +msgid "Resend link" +msgstr "" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "" @@ -806,7 +852,7 @@ msgid "Join %(name)s" msgstr "" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "" @@ -818,22 +864,24 @@ msgstr "" msgid "Request an Invitation" msgstr "" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +msgid "Confirm Email" +msgstr "" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1235,7 +1283,7 @@ msgid "Imported" msgstr "" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "" @@ -1303,7 +1351,7 @@ msgid "Notifications" msgstr "" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" @@ -1312,12 +1360,12 @@ msgstr "" msgid "password" msgstr "" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "" @@ -1493,16 +1541,20 @@ msgstr "" msgid "Login" msgstr "" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "" @@ -2315,7 +2367,15 @@ msgstr "" msgid "Allow invite requests" msgstr "" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "" @@ -2991,7 +3051,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index dbf7540c7..9fc28535e 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -288,7 +288,7 @@ msgstr "Clave Goodreads:" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -688,6 +688,60 @@ msgstr "Cerrar" msgid "Compose status" msgstr "Componer status" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Confirmar" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Enter a valid email address." +msgid "Confirm your email address" +msgstr "Ingrese una dirección de correo electrónico válida." + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Confirmar contraseña:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Enviar" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "Dirección de correo electrónico:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "Re-enviar invitación" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "Comunidad" @@ -816,7 +870,7 @@ msgid "Join %(name)s" msgstr "Unirse con %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Esta instancia está cerrada." @@ -828,22 +882,26 @@ msgstr "¡Gracias! Tu solicitud ha sido recibido." msgid "Request an Invitation" msgstr "Solicitar una invitación" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "Dirección de correo electrónico:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Enviar" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Tu cuenta" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Confirmar" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1250,7 +1308,7 @@ msgid "Imported" msgstr "Importado" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Crear una cuenta" @@ -1318,7 +1376,7 @@ msgid "Notifications" msgstr "Notificaciones" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nombre de usuario:" @@ -1327,12 +1385,12 @@ msgstr "Nombre de usuario:" msgid "password" msgstr "contraseña" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Iniciar sesión" @@ -1510,16 +1568,20 @@ msgstr "Tus listas" msgid "Login" msgstr "Iniciar sesión" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Contraseña:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Contactar a unx administradorx para recibir una invitación" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "Más sobre este sitio" @@ -2351,7 +2413,15 @@ msgstr "Permitir registración:" msgid "Allow invite requests" msgstr "Permitir solicitudes de invitación:" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Texto de registración cerrada:" @@ -3036,7 +3106,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3117,9 +3187,6 @@ msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" #~ msgid "Enter a valid integer." #~ msgstr "Ingrese un entero válido." -#~ msgid "Enter a valid email address." -#~ msgstr "Ingrese una dirección de correo electrónico válida." - #~ msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." #~ msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones" diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index b4405df5a..f0a559f97 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -286,7 +286,7 @@ msgstr "Clé Goodreads :" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -684,6 +684,60 @@ msgstr "Fermer" msgid "Compose status" msgstr "Rédiger un statut" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Confirmer" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "Adresse email :" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Confirmez le mot de passe :" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Valider" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "Adresse email :" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "Envoyer l’invitation de nouveau" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "Communauté" @@ -812,7 +866,7 @@ msgid "Join %(name)s" msgstr "Rejoignez %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Cette instance est fermée" @@ -824,22 +878,26 @@ msgstr "Merci ! Votre demande a bien été reçue." msgid "Request an Invitation" msgstr "Demander une invitation" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "Adresse email :" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Valider" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Votre compte" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Confirmer" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1246,7 +1304,7 @@ msgid "Imported" msgstr "Importé" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Créer un compte" @@ -1314,7 +1372,7 @@ msgid "Notifications" msgstr "Notifications" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nom du compte :" @@ -1323,12 +1381,12 @@ msgstr "Nom du compte :" msgid "password" msgstr "Mot de passe" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "Mot de passe oublié ?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Se connecter" @@ -1504,16 +1562,20 @@ msgstr "Vos listes" msgid "Login" msgstr "Connexion" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Mot de passe :" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Contacter un administrateur pour obtenir une invitation" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "En savoir plus sur ce site" @@ -2333,7 +2395,15 @@ msgstr "Autoriser les inscriptions" msgid "Allow invite requests" msgstr "Autoriser les demandes d’invitation" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Texte affiché lorsque les inscriptions sont closes :" @@ -3015,7 +3085,7 @@ msgstr "Ce fichier dépasse la taille limite : 10 Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3066,11 +3136,6 @@ msgstr "Un lien de réinitialisation a été envoyé à %s." #~ msgid "Enter a valid integer." #~ msgstr "Adresse email :" -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Enter a valid email address." -#~ msgstr "Adresse email :" - #, fuzzy #~| msgid "Email address:" #~ msgid "Enter a valid IPv4 address." diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 471de85d0..adb0d36c6 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -284,7 +284,7 @@ msgstr "Goodreads key:" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -681,6 +681,60 @@ msgstr "关闭" msgid "Compose status" msgstr "撰写状态" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "确认" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "邮箱地址:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "确认密码:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "提交" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "邮箱地址:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "重新发送请求" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "社区" @@ -807,7 +861,7 @@ msgid "Join %(name)s" msgstr "加入 %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "本实例不开放。" @@ -819,22 +873,26 @@ msgstr "谢谢你!我们已经收到了你的请求。" msgid "Request an Invitation" msgstr "请求邀请" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "邮箱地址:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "提交" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "你的帐号" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "确认" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1237,7 +1295,7 @@ msgid "Imported" msgstr "已导入" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "创建帐号" @@ -1305,7 +1363,7 @@ msgid "Notifications" msgstr "通知" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "用户名:" @@ -1314,12 +1372,12 @@ msgstr "用户名:" msgid "password" msgstr "密码" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "忘记了密码?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "登录" @@ -1495,16 +1553,20 @@ msgstr "你的列表" msgid "Login" msgstr "登录" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "密码:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "联系管理员以取得邀请" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "更多关于本站点的信息" @@ -2319,7 +2381,15 @@ msgstr "允许注册" msgid "Allow invite requests" msgstr "允许请求邀请" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "注册关闭文字:" @@ -2992,7 +3062,7 @@ msgstr "文件超过了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 40b12995b..c496bb924 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -288,7 +288,7 @@ msgstr "Goodreads key:" #: 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:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -687,6 +687,60 @@ msgstr "關閉" msgid "Compose status" msgstr "撰寫狀態" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "確認" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "郵箱地址:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "確認密碼:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "提交" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "郵箱地址:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "重新發送請求" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "社群" @@ -813,7 +867,7 @@ msgid "Join %(name)s" msgstr "加入 %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "本實例不開放。" @@ -825,22 +879,26 @@ msgstr "謝謝你!我們已經受到了你的請求。" msgid "Request an Invitation" msgstr "請求邀請" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "郵箱地址:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "提交" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "你的帳號" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "確認" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1247,7 +1305,7 @@ msgid "Imported" msgstr "已匯入" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "建立帳號" @@ -1315,7 +1373,7 @@ msgid "Notifications" msgstr "通知" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "使用者名稱:" @@ -1324,12 +1382,12 @@ msgstr "使用者名稱:" msgid "password" msgstr "密碼" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "忘記了密碼?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "登入" @@ -1505,16 +1563,20 @@ msgstr "你的列表" msgid "Login" msgstr "登入" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "密碼:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "聯絡管理員以取得邀請" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "關於本網站的更多" @@ -2338,7 +2400,15 @@ msgstr "允許註冊:" msgid "Allow invite requests" msgstr "允許請求邀請:" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "註冊關閉文字:" @@ -3011,7 +3081,7 @@ msgstr "檔案超過了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" From e198e663d1b821a596a56b12986a00441c86b815 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:48:16 -0700 Subject: [PATCH 0132/1024] Fixes names of site settings field in tests --- bookwyrm/tests/views/test_authentication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index bbafe7bd5..bd4b3b029 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -32,7 +32,7 @@ class AuthenticationViews(TestCase): self.anonymous_user.is_authenticated = False self.settings = models.SiteSettings.objects.create( - id=1, require_email_confirmation=False + id=1, require_confirm_email=False ) def test_login_get(self, _): From aad5de3b618b20d2c24cfe456f1f7a2e0324243d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 19:03:15 -0700 Subject: [PATCH 0133/1024] Improves cross-edition display for lists --- bookwyrm/templatetags/bookwyrm_tags.py | 2 +- bookwyrm/views/books.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 5cba5455f..4811f4fd5 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -12,7 +12,7 @@ register = template.Library() def get_rating(book, user): """get the overall rating of a book""" queryset = views.helpers.privacy_filter( - user, models.Review.objects.filter(book=book) + user, models.Review.objects.filter(book__in=book.parent_work.editions.all()) ) return queryset.aggregate(Avg("rating"))["rating__avg"] diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index d56e2f22c..6cd0427c1 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -65,6 +65,13 @@ class Book(View): queryset = queryset.select_related("user") paginated = Paginator(queryset, PAGE_LENGTH) + lists = privacy_filter( + request.user, + models.List.objects.filter( + listitem__approved=True, + listitem__book__in=book.parent_work.editions.all(), + ), + ) data = { "book": book, "statuses": paginated.get_page(request.GET.get("page")), @@ -75,9 +82,7 @@ class Book(View): if not user_statuses else None, "rating": reviews.aggregate(Avg("rating"))["rating__avg"], - "lists": privacy_filter( - request.user, book.list_set.filter(listitem__approved=True) - ), + "lists": lists, } if request.user.is_authenticated: From 0fa9fd7331e71dd981b8effa6faeb4aba61fada6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:28:24 -0700 Subject: [PATCH 0134/1024] Registration with confirm email tests --- bookwyrm/tests/views/test_authentication.py | 97 +++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index bd4b3b029..dc9f5dd53 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -132,6 +132,32 @@ class AuthenticationViews(TestCase): self.assertEqual(nutria.localname, "nutria-user.user_nutria") self.assertEqual(nutria.local, True) + def test_register_email_confirm(self, _): + """create a user""" + self.settings.require_confirm_email = True + self.settings.save() + + view = views.Register.as_view() + self.assertEqual(models.User.objects.count(), 1) + request = self.factory.post( + "register/", + { + "localname": "nutria", + "password": "mouseword", + "email": "aa@bb.cccc", + }, + ) + with patch("bookwyrm.views.authentication.login"): + response = view(request) + self.assertEqual(response.status_code, 302) + nutria = models.User.objects.get(localname="nutria") + self.assertEqual(nutria.username, "nutria@%s" % DOMAIN) + self.assertEqual(nutria.local, True) + + self.assertFalse(nutria.is_active) + self.assertEqual(nutria.deactivation_reason, "pending") + self.assertIsNotNone(nutria.confirmation_code) + def test_register_trailing_space(self, _): """django handles this so weirdly""" view = views.Register.as_view() @@ -251,3 +277,74 @@ class AuthenticationViews(TestCase): with self.assertRaises(Http404): response = view(request) self.assertEqual(models.User.objects.count(), 2) + + def test_confirm_email_code_get(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + self.local_user.is_active = False + self.local_user.deactivation_reason = "pending" + self.local_user.confirmation_code = "12345" + self.local_user.save( + broadcast=False, + update_fields=["is_active", "deactivation_reason", "confirmation_code"], + ) + view = views.ConfirmEmailCode.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = view(request, "12345") + self.assertEqual(result.url, "/login/confirmed") + self.assertEqual(result.status_code, 302) + + self.local_user.refresh_from_db() + self.assertTrue(self.local_user.is_active) + self.assertIsNone(self.local_user.deactivation_reason) + + request.user = self.local_user + result = view(request, "12345") + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_confirm_email_code_get_invalid_code(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + self.local_user.is_active = False + self.local_user.deactivation_reason = "pending" + self.local_user.confirmation_code = "12345" + self.local_user.save( + broadcast=False, + update_fields=["is_active", "deactivation_reason", "confirmation_code"], + ) + view = views.ConfirmEmailCode.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = view(request, "abcde") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertFalse(self.local_user.is_active) + self.assertEqual(self.local_user.deactivation_reason, "pending") + + def test_confirm_email_get(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + login = views.ConfirmEmail.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = login(request) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + + request.user = self.local_user + result = login(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) From 226c325099e1bd5ff723dd2c0df6549999067dc6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:37:18 -0700 Subject: [PATCH 0135/1024] Adds plaintext code to emails --- bookwyrm/templates/email/confirm/html_content.html | 6 ++++++ bookwyrm/templates/email/confirm/text_content.html | 3 +++ 2 files changed, 9 insertions(+) diff --git a/bookwyrm/templates/email/confirm/html_content.html b/bookwyrm/templates/email/confirm/html_content.html index b47642af7..231b0388e 100644 --- a/bookwyrm/templates/email/confirm/html_content.html +++ b/bookwyrm/templates/email/confirm/html_content.html @@ -11,4 +11,10 @@ One last step before you join {{ site_name }}! Please confirm your email address {% trans "Confirm Email" as text %} {% include 'email/snippets/action.html' with path=confirmation_link text=text %} +

+{% blocktrans trimmed %} +Or enter the code "{{ confirmation_code }}" at login. +{% endblocktrans %} +

+ {% endblock %} diff --git a/bookwyrm/templates/email/confirm/text_content.html b/bookwyrm/templates/email/confirm/text_content.html index e3d739383..847009e55 100644 --- a/bookwyrm/templates/email/confirm/text_content.html +++ b/bookwyrm/templates/email/confirm/text_content.html @@ -7,5 +7,8 @@ One last step before you join {{ site_name }}! Please confirm your email address {{ confirmation_link }} +{% blocktrans trimmed %} +Or enter the code "{{ confirmation_code }}" at login. +{% endblocktrans %} {% endblock %} From 68e4462486d03573b278ef5da42b73ce5fd7bf5d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:43:30 -0700 Subject: [PATCH 0136/1024] Make email a required html field in register form --- bookwyrm/templates/snippets/register_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/register_form.html b/bookwyrm/templates/snippets/register_form.html index cd7ea8063..9e610bd13 100644 --- a/bookwyrm/templates/snippets/register_form.html +++ b/bookwyrm/templates/snippets/register_form.html @@ -12,7 +12,7 @@
- + {% for error in register_form.email.errors %}

{{ error | escape }}

{% endfor %} From 38f614a526209e78b469e477261a8efef5d0ebda Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:56:30 -0700 Subject: [PATCH 0137/1024] Include generated notes in books stream --- bookwyrm/activitystreams.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index bad7c59f8..66dcad84e 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -358,25 +358,39 @@ def add_statuses_on_shelve(sender, instance, *args, **kwargs): """update books stream when user shelves a book""" if not instance.user.local: return - # check if the book is already on the user's shelves - if models.ShelfBook.objects.filter( - user=instance.user, book__in=instance.book.parent_work.editions.all() - ).exists(): + book = None + if hasattr(instance, "book"): + book = instance.book + elif instance.mention_books.exists(): + book = instance.mention_books.first() + if not book: return - BooksStream().add_book_statuses(instance.user, instance.book) + # check if the book is already on the user's shelves + editions = book.parent_work.editions.all() + if models.ShelfBook.objects.filter(user=instance.user, book__in=editions).exists(): + return + + BooksStream().add_book_statuses(instance.user, book) @receiver(signals.post_delete, sender=models.ShelfBook) # pylint: disable=unused-argument -def remove_statuses_on_shelve(sender, instance, *args, **kwargs): +def remove_statuses_on_unshelve(sender, instance, *args, **kwargs): """update books stream when user unshelves a book""" if not instance.user.local: return + + book = None + if hasattr(instance, "book"): + book = instance.book + elif instance.mention_books.exists(): + book = instance.mention_books.first() + if not book: + return # check if the book is actually unshelved, not just moved - if models.ShelfBook.objects.filter( - user=instance.user, book__in=instance.book.parent_work.editions.all() - ).exists(): + editions = book.parent_work.editions.all() + if models.ShelfBook.objects.filter(user=instance.user, book__in=editions).exists(): return BooksStream().remove_book_statuses(instance.user, instance.book) From 026c6ac025f2725f0e2805da4e7040e212a4d4a5 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 08:01:14 -0700 Subject: [PATCH 0138/1024] Mocks emailer in registration test --- bookwyrm/tests/views/test_authentication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index dc9f5dd53..22008e100 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -132,7 +132,8 @@ class AuthenticationViews(TestCase): self.assertEqual(nutria.localname, "nutria-user.user_nutria") self.assertEqual(nutria.local, True) - def test_register_email_confirm(self, _): + @patch("bookwyrm.emailing.send_email.delay") + def test_register_email_confirm(self, *_): """create a user""" self.settings.require_confirm_email = True self.settings.save() From 468f1f135c42b819f6f2f884dbe39fbf9101dd04 Mon Sep 17 00:00:00 2001 From: reese Date: Sat, 7 Aug 2021 11:35:07 -0500 Subject: [PATCH 0139/1024] update spanish translations --- locale/es/LC_MESSAGES/django.mo | Bin 42719 -> 44832 bytes locale/es/LC_MESSAGES/django.po | 135 ++++++++++---------------------- 2 files changed, 41 insertions(+), 94 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index 23869cf45428ccb9c4d7e0d8a06dc96b209e7775..c73db384d7792b0008f0fef891c4d286b5a253f7 100644 GIT binary patch delta 15136 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 LV$IFrOFI|=dHQfG delta 13429 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 E0Qt|D8~^|S diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 9fc28535e..31ccd53cd 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-07 01:35+0000\n" +"POT-Creation-Date: 2021-08-07 16:23+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -100,10 +100,8 @@ msgid "Home" msgstr "Hogar" #: bookwyrm/settings.py:124 -#, fuzzy -#| msgid "Book Title" msgid "Books Timeline" -msgstr "Título" +msgstr "Línea temporal de libros" #: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 @@ -132,10 +130,8 @@ msgid "Simplified Chinese" msgstr "Chino simplificado" #: bookwyrm/settings.py:175 -#, fuzzy -#| msgid "Additional info:" msgid "Traditional Chinese" -msgstr "Más informacion:" +msgstr "Chino tradicional" #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" @@ -190,10 +186,8 @@ msgid "View on Inventaire" msgstr "Ver en Inventaire" #: bookwyrm/templates/author/author.html:85 -#, fuzzy -#| msgid "View on OpenLibrary" msgid "View on LibraryThing" -msgstr "Ver en OpenLibrary" +msgstr "Ver en LibraryThing" #: bookwyrm/templates/author/author.html:93 msgid "View on Goodreads" @@ -534,16 +528,12 @@ msgid "Authors" msgstr "Autores" #: bookwyrm/templates/book/edit_book.html:202 -#, fuzzy, python-format -#| msgid "Remove from %(name)s" msgid "Remove %(name)s" -msgstr "Quitar de %(name)s" +msgstr "Quitar %(name)s" #: bookwyrm/templates/book/edit_book.html:205 -#, fuzzy, python-format -#| msgid "Remove from %(name)s" msgid "Author page for %(name)s" -msgstr "Quitar de %(name)s" +msgstr "Página de autor por %(name)s" #: bookwyrm/templates/book/edit_book.html:212 msgid "Add Authors:" @@ -689,16 +679,12 @@ msgid "Compose status" msgstr "Componer status" #: bookwyrm/templates/confirm_email/confirm_email.html:4 -#, fuzzy -#| msgid "Confirm" msgid "Confirm email" -msgstr "Confirmar" +msgstr "Confirmar correo electrónico" #: bookwyrm/templates/confirm_email/confirm_email.html:7 -#, fuzzy -#| msgid "Enter a valid email address." msgid "Confirm your email address" -msgstr "Ingrese una dirección de correo electrónico válida." +msgstr "Confirmar tu dirección de correo electrónico" #: bookwyrm/templates/confirm_email/confirm_email.html:13 msgid "A confirmation code has been sent to the email address you used to register your account." @@ -709,10 +695,8 @@ msgid "Sorry! We couldn't find that code." msgstr "" #: bookwyrm/templates/confirm_email/confirm_email.html:19 -#, fuzzy -#| msgid "Confirm password:" msgid "Confirmation code:" -msgstr "Confirmar contraseña:" +msgstr "Código de confirmación:" #: bookwyrm/templates/confirm_email/confirm_email.html:25 #: bookwyrm/templates/discover/landing_layout.html:70 @@ -737,10 +721,8 @@ msgid "Email address:" msgstr "Dirección de correo electrónico:" #: bookwyrm/templates/confirm_email/resend_form.html:17 -#, fuzzy -#| msgid "Re-send invite" msgid "Resend link" -msgstr "Re-enviar invitación" +msgstr "Re-enviar enlace" #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" @@ -791,10 +773,8 @@ msgstr "Activ@ recientemente" #: bookwyrm/templates/directory/user_card.html:18 #: bookwyrm/templates/user/user_preview.html:16 #: bookwyrm/templates/user/user_preview.html:17 -#, fuzzy -#| msgid "Your Account" msgid "Locked account" -msgstr "Tu cuenta" +msgstr "Cuenta bloqueada" #: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" @@ -893,15 +873,23 @@ msgid "One last step before you join %(site_name)s! Please confirm your email ad msgstr "" #: bookwyrm/templates/email/confirm/html_content.html:11 -#, fuzzy -#| msgid "Confirm" msgid "Confirm Email" -msgstr "Confirmar" +msgstr "Confirmar correo electrónico" + +#: bookwyrm/templates/email/confirm/html_content.html:15 +#, python-format +msgid "Or enter the code \"%(confirmation_code)s\" at login." +msgstr "" #: bookwyrm/templates/email/confirm/subject.html:2 msgid "Please confirm your email" msgstr "" +#: bookwyrm/templates/email/confirm/text_content.html:10 +#, python-format +msgid "Or enter the code \"%(confirmation_code)s\" at login." +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -983,10 +971,8 @@ msgid "You have no messages right now." msgstr "No tienes ningún mensaje en este momento." #: bookwyrm/templates/feed/feed.html:22 -#, fuzzy, python-format -#| msgid "load 0 unread status(es)" msgid "load 0 unread status(es)" -msgstr "cargar 0 status(es) no leídos" +msgstr "cargar 0 status(es) no leído(s)" #: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" @@ -1229,10 +1215,8 @@ msgid "Import Status" msgstr "Status de importación" #: bookwyrm/templates/import_status.html:11 -#, fuzzy -#| msgid "Back to reports" msgid "Back to imports" -msgstr "Volver a los informes" +msgstr "Volver a las importaciones" #: bookwyrm/templates/import_status.html:15 msgid "Import started:" @@ -1281,10 +1265,8 @@ msgid "Successfully imported" msgstr "Importado exitosamente" #: bookwyrm/templates/import_status.html:114 -#, fuzzy -#| msgid "Import still in progress." msgid "Import Progress" -msgstr "Importación todavia en progreso" +msgstr "Progreso de importación" #: bookwyrm/templates/import_status.html:119 msgid "Book" @@ -1399,10 +1381,8 @@ msgid "Join" msgstr "Unirse" #: bookwyrm/templates/layout.html:213 -#, fuzzy -#| msgid "About this server" msgid "About this instance" -msgstr "Sobre este servidor" +msgstr "Sobre esta instancia" #: bookwyrm/templates/layout.html:217 msgid "Contact site admin" @@ -1836,10 +1816,8 @@ msgstr "Nueva contraseña:" #: bookwyrm/templates/preferences/delete_user.html:7 #: bookwyrm/templates/preferences/delete_user.html:26 #: bookwyrm/templates/preferences/layout.html:23 -#, fuzzy -#| msgid "Create an Account" msgid "Delete Account" -msgstr "Crear una cuenta" +msgstr "Quitar cuenta" #: bookwyrm/templates/preferences/delete_user.html:12 msgid "Permanently delete account" @@ -1859,10 +1837,8 @@ msgid "Show set reading goal prompt in feed:" msgstr "Mostrar meta de lectura en el feed:" #: bookwyrm/templates/preferences/edit_user.html:58 -#, fuzzy -#| msgid "Post privacy" msgid "Default post privacy:" -msgstr "Privacidad de publicación" +msgstr "Privacidad de publicación por defecto:" #: bookwyrm/templates/preferences/edit_user.html:70 #, python-format @@ -1886,22 +1862,16 @@ msgid "Relationships" msgstr "Relaciones" #: bookwyrm/templates/reading_progress/finish.html:5 -#, fuzzy, python-format -#| msgid "Finish \"%(book_title)s\"" msgid "Finish \"%(book_title)s\"" -msgstr "Terminar \"%(book_title)s\"" +msgstr "Terminar \"%(book_title)s\"" #: bookwyrm/templates/reading_progress/start.html:5 -#, fuzzy, python-format -#| msgid "Edit \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" -msgstr "Editar \"%(book_title)s\"" +msgstr "Empezar \"%(book_title)s\"" #: bookwyrm/templates/reading_progress/want.html:5 -#, fuzzy, python-format -#| msgid "Want to Read \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" -msgstr "Quiero leer \"%(book_title)s\"" +msgstr "Quiero leer \"%(book_title)s\"" #: bookwyrm/templates/rss/title.html:5 #: bookwyrm/templates/snippets/status/status_header.html:36 @@ -1967,10 +1937,8 @@ msgstr "Administrar usuarios" #: bookwyrm/templates/settings/admin_layout.html:39 #: bookwyrm/templates/settings/federation.html:3 #: bookwyrm/templates/settings/federation.html:5 -#, fuzzy -#| msgid "Federated Servers" msgid "Federated Instances" -msgstr "Servidores federalizados" +msgstr "Instancias federalizadas" #: bookwyrm/templates/settings/admin_layout.html:44 msgid "Instance Settings" @@ -2097,17 +2065,13 @@ msgstr "inactivo" #: bookwyrm/templates/settings/federation.html:10 #: bookwyrm/templates/settings/server_blocklist.html:3 #: bookwyrm/templates/settings/server_blocklist.html:20 -#, fuzzy -#| msgid "View instance" msgid "Add instance" -msgstr "Ver instancia" +msgstr "Agregar instancia" #: bookwyrm/templates/settings/edit_server.html:7 #: bookwyrm/templates/settings/server_blocklist.html:7 -#, fuzzy -#| msgid "Back to server list" msgid "Back to instance list" -msgstr "Volver a la lista de servidores" +msgstr "Volver a la lista de instancias" #: bookwyrm/templates/settings/edit_server.html:16 #: bookwyrm/templates/settings/server_blocklist.html:16 @@ -2217,10 +2181,8 @@ msgstr "Todos los usuarios en esta instancia serán re-activados." #: bookwyrm/templates/settings/federation.html:19 #: bookwyrm/templates/user_admin/server_filter.html:5 -#, fuzzy -#| msgid "Instance Name:" msgid "Instance name" -msgstr "Nombre de instancia:" +msgstr "Nombre de instancia" #: bookwyrm/templates/settings/federation.html:23 msgid "Date federated" @@ -2402,16 +2364,12 @@ msgid "Additional info:" msgstr "Más informacion:" #: bookwyrm/templates/settings/site.html:85 -#, fuzzy -#| msgid "Allow registration:" msgid "Allow registration" -msgstr "Permitir registración:" +msgstr "Permitir registración" #: bookwyrm/templates/settings/site.html:91 -#, fuzzy -#| msgid "Allow invite requests:" msgid "Allow invite requests" -msgstr "Permitir solicitudes de invitación:" +msgstr "Permitir solicitudes de invitación" #: bookwyrm/templates/settings/site.html:97 msgid "Require users to confirm email address" @@ -2442,10 +2400,8 @@ msgid "No cover" msgstr "Sin portada" #: bookwyrm/templates/snippets/book_titleby.html:6 -#, fuzzy, python-format -#| msgid "%(title)s by " msgid "%(title)s by" -msgstr "%(title)s por " +msgstr "%(title)s por" #: bookwyrm/templates/snippets/boost_button.html:20 #: bookwyrm/templates/snippets/boost_button.html:21 @@ -2673,8 +2629,6 @@ msgid "page %(page)s of %(total_pages)s" msgstr "página %(page)s de %(total_pages)s" #: bookwyrm/templates/snippets/page_text.html:6 -#, fuzzy, python-format -#| msgid "page %(page)s" msgid "page %(page)s" msgstr "página %(pages)s" @@ -2862,10 +2816,8 @@ msgstr[1] "%(shared_books)s libros en tus estantes" #: bookwyrm/templates/snippets/suggested_users.html:31 #: bookwyrm/templates/user/user_preview.html:36 -#, fuzzy -#| msgid "followed you" msgid "Follows you" -msgstr "te siguió" +msgstr "Te sigue" #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" @@ -3018,11 +2970,8 @@ msgstr[0] "%(mutuals_display)s seguidor que sigues" msgstr[1] "%(mutuals_display)s seguidores que sigues" #: bookwyrm/templates/user/user_preview.html:38 -#, fuzzy -#| msgid "follower you follow" -#| msgid_plural "followers you follow" msgid "No followers you follow" -msgstr "seguidor que tu sigues" +msgstr "Ningún seguidor que tu sigues" #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" @@ -3047,10 +2996,8 @@ msgid "Last Active" msgstr "Actividad reciente" #: bookwyrm/templates/user_admin/user_admin.html:38 -#, fuzzy -#| msgid "View instance" msgid "Remote instance" -msgstr "Ver instancia" +msgstr "Instancia remota" #: bookwyrm/templates/user_admin/user_admin.html:47 msgid "Active" From a0d2f3897016dbeb37cf214102d2cc56f5c81ee4 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Sat, 7 Aug 2021 19:35:43 +0200 Subject: [PATCH 0140/1024] [french] Translate strings about email confirmation. --- locale/fr_FR/LC_MESSAGES/django.po | 38 +++++++++++------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index f0a559f97..badfcdcaf 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -685,30 +685,24 @@ msgid "Compose status" msgstr "Rédiger un statut" #: bookwyrm/templates/confirm_email/confirm_email.html:4 -#, fuzzy -#| msgid "Confirm" msgid "Confirm email" -msgstr "Confirmer" +msgstr "Confirmation de l’email" #: bookwyrm/templates/confirm_email/confirm_email.html:7 -#, fuzzy -#| msgid "Email address:" msgid "Confirm your email address" -msgstr "Adresse email :" +msgstr "Veuillez confirmer votre adresse email" #: bookwyrm/templates/confirm_email/confirm_email.html:13 msgid "A confirmation code has been sent to the email address you used to register your account." -msgstr "" +msgstr "Un code de confirmation a été envoyé à l’adresse email rattachée à votre compte." #: bookwyrm/templates/confirm_email/confirm_email.html:15 msgid "Sorry! We couldn't find that code." -msgstr "" +msgstr "Pardon ! Nous ne reconnaissons pas ce code." #: bookwyrm/templates/confirm_email/confirm_email.html:19 -#, fuzzy -#| msgid "Confirm password:" msgid "Confirmation code:" -msgstr "Confirmez le mot de passe :" +msgstr "Code de confirmation :" #: bookwyrm/templates/confirm_email/confirm_email.html:25 #: bookwyrm/templates/discover/landing_layout.html:70 @@ -718,11 +712,11 @@ msgstr "Valider" #: bookwyrm/templates/confirm_email/confirm_email.html:32 msgid "Can't find your code?" -msgstr "" +msgstr "Vous ne trouvez pas votre code ?" #: bookwyrm/templates/confirm_email/resend_form.html:4 msgid "Resend confirmation link" -msgstr "" +msgstr "Envoyer le lien de confirmation de nouveau" #: bookwyrm/templates/confirm_email/resend_form.html:11 #: bookwyrm/templates/discover/landing_layout.html:64 @@ -733,10 +727,8 @@ msgid "Email address:" msgstr "Adresse email :" #: bookwyrm/templates/confirm_email/resend_form.html:17 -#, fuzzy -#| msgid "Re-send invite" msgid "Resend link" -msgstr "Envoyer l’invitation de nouveau" +msgstr "Envoyer le lien de nouveau" #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" @@ -886,17 +878,15 @@ msgstr "Votre compte" #: bookwyrm/templates/email/confirm/text_content.html:4 #, python-format msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" -msgstr "" +msgstr "Une dernière petite étape avant de rejoindre %(site_name)s ! Veuillez confirmer votre adresse email en cliquant le lien ci‑dessous :" #: bookwyrm/templates/email/confirm/html_content.html:11 -#, fuzzy -#| msgid "Confirm" msgid "Confirm Email" -msgstr "Confirmer" +msgstr "Confirmation de l’email" #: bookwyrm/templates/email/confirm/subject.html:2 msgid "Please confirm your email" -msgstr "" +msgstr "Veuillez confirmer votre adresse email" #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 @@ -1564,7 +1554,7 @@ msgstr "Connexion" #: bookwyrm/templates/login.html:16 msgid "Success! Email address confirmed." -msgstr "" +msgstr "Bravo ! L’adresse email a été confirmée." #: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 @@ -2397,11 +2387,11 @@ msgstr "Autoriser les demandes d’invitation" #: bookwyrm/templates/settings/site.html:97 msgid "Require users to confirm email address" -msgstr "" +msgstr "Demander aux utilisateurs et utilisatrices de confirmer leur adresse email" #: bookwyrm/templates/settings/site.html:99 msgid "(Recommended if registration is open)" -msgstr "" +msgstr "(Recommandé si les inscriptions sont ouvertes)" #: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" From cce7d9a6484af4c203105e4c49fafe9de5ba0591 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 10:59:55 -0700 Subject: [PATCH 0141/1024] Don't skip updates statuses when adding to streams Generated note books are added post-initial save --- bookwyrm/activitystreams.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 66dcad84e..754b4b159 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -260,9 +260,6 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): stream.remove_object_from_related_stores(instance) return - if not created: - return - for stream in streams.values(): stream.add_status(instance) From 040758c833ea4670aa955f676091ae5564a396da Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 11:15:02 -0700 Subject: [PATCH 0142/1024] Renames "discover" --- .../{discover => landing}/about.html | 2 +- .../discover.html => landing/landing.html} | 14 +++++------ .../{discover => landing}/landing_layout.html | 0 .../{discover => landing}/large-book.html | 0 .../{discover => landing}/small-book.html | 1 - bookwyrm/tests/views/test_landing.py | 4 ++-- bookwyrm/views/__init__.py | 3 ++- bookwyrm/views/discover.py | 23 +++++++++++++++++++ bookwyrm/views/helpers.py | 4 ++-- bookwyrm/views/landing.py | 14 +++++------ 10 files changed, 44 insertions(+), 21 deletions(-) rename bookwyrm/templates/{discover => landing}/about.html (95%) rename bookwyrm/templates/{discover/discover.html => landing/landing.html} (72%) rename bookwyrm/templates/{discover => landing}/landing_layout.html (100%) rename bookwyrm/templates/{discover => landing}/large-book.html (100%) rename bookwyrm/templates/{discover => landing}/small-book.html (99%) create mode 100644 bookwyrm/views/discover.py diff --git a/bookwyrm/templates/discover/about.html b/bookwyrm/templates/landing/about.html similarity index 95% rename from bookwyrm/templates/discover/about.html rename to bookwyrm/templates/landing/about.html index a6f3a026a..dd7036c4f 100644 --- a/bookwyrm/templates/discover/about.html +++ b/bookwyrm/templates/landing/about.html @@ -1,4 +1,4 @@ -{% extends 'discover/landing_layout.html' %} +{% extends 'landing/landing_layout.html' %} {% load i18n %} {% block panel %} diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/landing/landing.html similarity index 72% rename from bookwyrm/templates/discover/discover.html rename to bookwyrm/templates/landing/landing.html index d553c3680..38180c3bf 100644 --- a/bookwyrm/templates/discover/discover.html +++ b/bookwyrm/templates/landing/landing.html @@ -1,4 +1,4 @@ -{% extends 'discover/landing_layout.html' %} +{% extends 'landing/landing_layout.html' %} {% load i18n %} {% block panel %} @@ -10,18 +10,18 @@
- {% include 'discover/large-book.html' with book=books.0 %} + {% include 'landing/large-book.html' with book=books.0 %}
- {% include 'discover/small-book.html' with book=books.1 %} + {% include 'landing/small-book.html' with book=books.1 %}
- {% include 'discover/small-book.html' with book=books.2 %} + {% include 'landing/small-book.html' with book=books.2 %}
@@ -30,18 +30,18 @@
- {% include 'discover/small-book.html' with book=books.3 %} + {% include 'landing/small-book.html' with book=books.3 %}
- {% include 'discover/small-book.html' with book=books.4 %} + {% include 'landing/small-book.html' with book=books.4 %}
- {% include 'discover/large-book.html' with book=books.5 %} + {% include 'landing/large-book.html' with book=books.5 %}
diff --git a/bookwyrm/templates/discover/landing_layout.html b/bookwyrm/templates/landing/landing_layout.html similarity index 100% rename from bookwyrm/templates/discover/landing_layout.html rename to bookwyrm/templates/landing/landing_layout.html diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/landing/large-book.html similarity index 100% rename from bookwyrm/templates/discover/large-book.html rename to bookwyrm/templates/landing/large-book.html diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/landing/small-book.html similarity index 99% rename from bookwyrm/templates/discover/small-book.html rename to bookwyrm/templates/landing/small-book.html index 73133de45..3f7cbecc3 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/landing/small-book.html @@ -1,4 +1,3 @@ - {% load bookwyrm_tags %} {% load i18n %} diff --git a/bookwyrm/tests/views/test_landing.py b/bookwyrm/tests/views/test_landing.py index 4d1531e45..476da74b1 100644 --- a/bookwyrm/tests/views/test_landing.py +++ b/bookwyrm/tests/views/test_landing.py @@ -54,9 +54,9 @@ class LandingViews(TestCase): result.render() self.assertEqual(result.status_code, 200) - def test_discover(self): + def test_landing(self): """there are so many views, this just makes sure it LOADS""" - view = views.Discover.as_view() + view = views.Landing.as_view() request = self.factory.get("") result = view(request) self.assertIsInstance(result, TemplateResponse) diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index eccb7f5e5..15b55accb 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -7,6 +7,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 .discover import Discover from .edit_user import EditUser, DeleteUser from .federation import Federation, FederatedServer from .federation import AddFederatedServer, ImportServerBlocklist @@ -22,7 +23,7 @@ from .interaction import Favorite, Unfavorite, Boost, Unboost from .invite import ManageInvites, Invite, InviteRequest from .invite import ManageInviteRequests, ignore_invite_request from .isbn import Isbn -from .landing import About, Home, Discover +from .landing import About, Home, Landing from .list import Lists, List, Curate, UserLists from .notifications import Notifications from .outbox import Outbox diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py new file mode 100644 index 000000000..9bef6974d --- /dev/null +++ b/bookwyrm/views/discover.py @@ -0,0 +1,23 @@ +""" What's up locally """ +from django.contrib.auth.decorators import login_required +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.views import View + +from bookwyrm import forms +from . import helpers + + +# pylint: disable= no-self-use +@method_decorator(login_required, name="dispatch") +class Discover(View): + """preview of recently reviewed books""" + + def get(self, request): + """tiled book activity page""" + data = { + "register_form": forms.RegisterForm(), + "request_form": forms.InviteRequestForm(), + "books": helpers.get_landing_books(), + } + return TemplateResponse(request, "landing/landing.html", data) diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 42aa48f0e..f757cec95 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -162,8 +162,8 @@ def is_blocked(viewer, user): return False -def get_discover_books(): - """list of books for the discover page""" +def get_landing_books(): + """list of books for the landing page""" return list( set( models.Edition.objects.filter( diff --git a/bookwyrm/views/landing.py b/bookwyrm/views/landing.py index 1361935ee..6f480b70f 100644 --- a/bookwyrm/views/landing.py +++ b/bookwyrm/views/landing.py @@ -13,22 +13,22 @@ class About(View): def get(self, request): """more information about the instance""" - return TemplateResponse(request, "discover/about.html") + return TemplateResponse(request, "landing/about.html") class Home(View): - """discover page or home feed depending on auth""" + """landing page or home feed depending on auth""" def get(self, request): """this is the same as the feed on the home tab""" if request.user.is_authenticated: feed_view = Feed.as_view() return feed_view(request, "home") - discover_view = Discover.as_view() - return discover_view(request) + landing_view = Landing.as_view() + return landing_view(request) -class Discover(View): +class Landing(View): """preview of recently reviewed books""" def get(self, request): @@ -36,6 +36,6 @@ class Discover(View): data = { "register_form": forms.RegisterForm(), "request_form": forms.InviteRequestForm(), - "books": helpers.get_discover_books(), + "books": helpers.get_landing_books(), } - return TemplateResponse(request, "discover/discover.html", data) + return TemplateResponse(request, "landing/landing.html", data) From b5153f3df12a96010fc35c852a47a0a6f0956876 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 12:33:45 -0700 Subject: [PATCH 0143/1024] WIP --- bookwyrm/templates/discover/discover.html | 54 +++++++++++++++++++++ bookwyrm/templates/discover/large-book.html | 38 +++++++++++++++ bookwyrm/templates/discover/small-book.html | 41 ++++++++++++++++ bookwyrm/templates/landing/large-book.html | 2 +- bookwyrm/templates/landing/small-book.html | 2 +- bookwyrm/views/discover.py | 25 +++++++--- 6 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/templates/discover/discover.html create mode 100644 bookwyrm/templates/discover/large-book.html create mode 100644 bookwyrm/templates/discover/small-book.html diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/discover/discover.html new file mode 100644 index 000000000..0a419e51b --- /dev/null +++ b/bookwyrm/templates/discover/discover.html @@ -0,0 +1,54 @@ +{% extends "layout.html" %} +{% load i18n %} + +{% block title %}{% trans "Discover" %}{% endblock %} + +{% block content %} + +
+

{% trans "Discover" %}

+
+ +
+
+
+
+ {% include 'discover/large-book.html' with status=large.0 %} +
+
+
+
+
+ {% include 'discover/small-book.html' with status=small.0 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small.1 %} +
+
+
+
+
+
+
+
+ {% include 'discover/small-book.html' with status=small.2 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small.3 %} +
+
+
+
+
+ {% include 'discover/large-book.html' with status=large.1 %} +
+
+
+
+ + +{% endblock %} diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html new file mode 100644 index 000000000..b273d4318 --- /dev/null +++ b/bookwyrm/templates/discover/large-book.html @@ -0,0 +1,38 @@ +{% load bookwyrm_tags %} +{% load markdown %} +{% load i18n %} + +{% if book %} + {% with book=book %} +
+
+ {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} + + {% include 'snippets/stars.html' with rating=book|rating:request.user %} +
+ + +
+

+ {{ book.title }} +

+ + {% if book.authors %} +

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

+ {% endif %} + + {% if book|book_description %} +
+ {{ book|book_description|to_markdown|safe|truncatewords_html:50 }} +
+ {% endif %} +
+
+ {% endwith %} +{% endif %} diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html new file mode 100644 index 000000000..052a540cf --- /dev/null +++ b/bookwyrm/templates/discover/small-book.html @@ -0,0 +1,41 @@ +{% load bookwyrm_tags %} +{% load utilities %} +{% load i18n %} + +{% if status %} + {% with book=status.book %} + + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %} + + + {% include 'snippets/stars.html' with rating=book|rating:request.user %} + +

+ {{ book.title }} +

+ + {% if book.authors %} +

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

+ {% endif %} + + + + {% endwith %} +{% endif %} diff --git a/bookwyrm/templates/landing/large-book.html b/bookwyrm/templates/landing/large-book.html index 93026991e..b273d4318 100644 --- a/bookwyrm/templates/landing/large-book.html +++ b/bookwyrm/templates/landing/large-book.html @@ -23,7 +23,7 @@ {% if book.authors %}

{% trans "by" %} - {% include 'snippets/authors.html' %} + {% include 'snippets/authors.html' with limit=3 %}

{% endif %} diff --git a/bookwyrm/templates/landing/small-book.html b/bookwyrm/templates/landing/small-book.html index 3f7cbecc3..2ca505d94 100644 --- a/bookwyrm/templates/landing/small-book.html +++ b/bookwyrm/templates/landing/small-book.html @@ -16,7 +16,7 @@ {% if book.authors %}

{% trans "by" %} - {% include 'snippets/authors.html' %} + {% include 'snippets/authors.html' with limit=3 %}

{% endif %} {% endwith %} diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py index 9bef6974d..685a4ded7 100644 --- a/bookwyrm/views/discover.py +++ b/bookwyrm/views/discover.py @@ -1,11 +1,14 @@ """ What's up locally """ from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator +from django.db.models import Q from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views import View -from bookwyrm import forms -from . import helpers +from bookwyrm import models +from bookwyrm.settings import PAGE_LENGTH +from .helpers import privacy_filter # pylint: disable= no-self-use @@ -15,9 +18,19 @@ class Discover(View): def get(self, request): """tiled book activity page""" + activities = privacy_filter( + request.user, + models.Status.objects.select_subclasses().filter( + Q(comment__isnull=False) + | Q(review__isnull=False) + | Q(quotation__isnull=False), + user__local=True + ), + #privacy_levels=["public"] + ) + #paginated = Paginator(activities, PAGE_LENGTH) data = { - "register_form": forms.RegisterForm(), - "request_form": forms.InviteRequestForm(), - "books": helpers.get_landing_books(), + "large": activities.filter(~Q(review__isnull=True, review__content=None))[:2], + "small": activities.filter(~Q(content=None))[:4], } - return TemplateResponse(request, "landing/landing.html", data) + return TemplateResponse(request, "discover/discover.html", data) From 06c5ae06a6aec5422d830a43dd85db0e1734ec52 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Sat, 7 Aug 2021 21:47:30 +0200 Subject: [PATCH 0144/1024] [french] Compile French locale. --- locale/fr_FR/LC_MESSAGES/django.mo | Bin 45471 -> 46960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index f8ade2a391ba574da54afa6f45e1bf1ad55f9372..98bc29095737fda2d84bcd909167dd90097fb8e7 100644 GIT binary patch delta 14975 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 Sa}roL_b-fR+$^^^NCW_!G=i!C From e3cbf306847b55cdc04875b335f11271f6857143 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 14:38:19 -0700 Subject: [PATCH 0145/1024] Local discovery view --- bookwyrm/templates/discover/discover.html | 87 +++++++++++++------ bookwyrm/templates/discover/large-book.html | 66 ++++++++++---- bookwyrm/templates/discover/small-book.html | 43 +++++---- .../templates/snippets/follow_button.html | 20 ++++- bookwyrm/views/discover.py | 18 ++-- 5 files changed, 166 insertions(+), 68 deletions(-) diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/discover/discover.html index 0a419e51b..01ef21869 100644 --- a/bookwyrm/templates/discover/discover.html +++ b/bookwyrm/templates/discover/discover.html @@ -5,50 +5,85 @@ {% block content %} -
-

{% trans "Discover" %}

-
+
+
+

{% trans "Discover" %}

+

+ {% blocktrans trimmed with site_name=site.name %} + See what's new in the local {{ site_name }} community + {% endblocktrans %} +

+
-
-
-
+
+
- {% include 'discover/large-book.html' with status=large.0 %} + {% include 'discover/large-book.html' with status=large_activities.0 %}
-
-
+
+
+ {% include 'discover/large-book.html' with status=large_activities.1 %} +
+
+
+ +
+
+
- {% include 'discover/small-book.html' with status=small.0 %} + {% include 'discover/large-book.html' with status=large_activities.2 %}
-
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.0 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.1 %} +
+
+
+
+
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.2 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.3 %} +
+
+
+
- {% include 'discover/small-book.html' with status=small.1 %} + {% include 'discover/large-book.html' with status=large_activities.3 %}
-
-
-
-
- {% include 'discover/small-book.html' with status=small.2 %} -
-
-
-
- {% include 'discover/small-book.html' with status=small.3 %} -
+ +
+
+
+ {% include 'discover/large-book.html' with status=large_activities.4 %}
-
+
- {% include 'discover/large-book.html' with status=large.1 %} + {% include 'discover/large-book.html' with status=large_activities.5 %}
- +
+ {% include 'snippets/pagination.html' with page=large_activities %} +
{% endblock %} diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index b273d4318..81620be1c 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -1,37 +1,67 @@ {% load bookwyrm_tags %} -{% load markdown %} {% load i18n %} -{% if book %} - {% with book=book %} +{% if status %} + {% with book=status.book %}
-
+
{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} -
- - -
-

+

{{ book.title }}

{% if book.authors %} -

- {% trans "by" %} - {% include 'snippets/authors.html' with limit=3 %} -

+

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

{% endif %} - {% if book|book_description %} -
- {{ book|book_description|to_markdown|safe|truncatewords_html:50 }} -
- {% endif %} + {% include 'snippets/shelve_button/shelve_button.html' %} +
+ +
+
+ +
+

+ + {{ status.user.display_name }} + + + {% if status.status_type == 'GeneratedNote' %} + {{ status.content|safe }} + {% elif status.status_type == 'Rating' %} + {% trans "rated" %} + {% elif status.status_type == 'Review' %} + {% trans "reviewed" %} + {% elif status.status_type == 'Comment' %} + {% trans "commented on" %} + {% elif status.status_type == 'Quotation' %} + {% trans "quoted" %} + {% endif %} + + {{ book.title }} +

+
+
+ +
+ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %} +
+ +
+ {% include "snippets/status/content_status.html" with hide_book=True %} +
{% endwith %} diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html index 052a540cf..1318c8bdc 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/discover/small-book.html @@ -5,23 +5,14 @@ {% if status %} {% with book=status.book %} - {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %} + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto align to-b to-l' %} - {% include 'snippets/stars.html' with rating=book|rating:request.user %} +
+ {% include 'snippets/shelve_button/shelve_button.html' %} +
-

- {{ book.title }} -

- - {% if book.authors %} -

- {% trans "by" %} - {% include 'snippets/authors.html' with limit=3 %} -

- {% endif %} - -
+
-

+

{{ status.user.display_name }} + + {% if status.status_type == 'GeneratedNote' %} + {{ status.content|safe }} + {% elif status.status_type == 'Rating' %} + {% trans "rated" %} + {% elif status.status_type == 'Review' %} + {% trans "reviewed" %} + {% elif status.status_type == 'Comment' %} + {% trans "commented on" %} + {% elif status.status_type == 'Quotation' %} + {% trans "quoted" %} + {% endif %} + + {{ book.title }}

+ {% if status.rating %} +

+ {% include 'snippets/stars.html' with rating=status.rating %} +

+ {% endif %}
+
+ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %} +
{% endwith %} {% endif %} diff --git a/bookwyrm/templates/snippets/follow_button.html b/bookwyrm/templates/snippets/follow_button.html index 0cbe6b8cd..8cafad7f9 100644 --- a/bookwyrm/templates/snippets/follow_button.html +++ b/bookwyrm/templates/snippets/follow_button.html @@ -9,15 +9,29 @@ {% csrf_token %} - +
diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py index 685a4ded7..0b1fae2b5 100644 --- a/bookwyrm/views/discover.py +++ b/bookwyrm/views/discover.py @@ -7,7 +7,6 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import models -from bookwyrm.settings import PAGE_LENGTH from .helpers import privacy_filter @@ -24,13 +23,20 @@ class Discover(View): Q(comment__isnull=False) | Q(review__isnull=False) | Q(quotation__isnull=False), - user__local=True + user__local=True, ), - #privacy_levels=["public"] + privacy_levels=["public"], ) - #paginated = Paginator(activities, PAGE_LENGTH) + large_activities = Paginator( + activities.filter(~Q(content=None), ~Q(content="")), 6 + ) + small_activities = Paginator( + activities.filter(Q(content=None) | Q(content="")), 4 + ) + + page = request.GET.get("page") data = { - "large": activities.filter(~Q(review__isnull=True, review__content=None))[:2], - "small": activities.filter(~Q(content=None))[:4], + "large_activities": large_activities.get_page(page), + "small_activities": small_activities.get_page(page), } return TemplateResponse(request, "discover/discover.html", data) From 2eb37663b6a032aac0b2bf227c4e3f8230cf71f6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 14:46:33 -0700 Subject: [PATCH 0146/1024] Adds mock to inbox test --- bookwyrm/tests/views/inbox/test_inbox_create.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_create.py b/bookwyrm/tests/views/inbox/test_inbox_create.py index f93354bfb..6e8917238 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_create.py +++ b/bookwyrm/tests/views/inbox/test_inbox_create.py @@ -47,7 +47,8 @@ class InboxCreate(TestCase): } models.SiteSettings.objects.create() - def test_create_status(self, _): + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_create_status(self, *_): """the "it justs works" mode""" datafile = pathlib.Path(__file__).parent.joinpath( "../../data/ap_quotation.json" From 760bd5a63fb51671f945bcb2f614eca41240d574 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 15:10:09 -0700 Subject: [PATCH 0147/1024] Fixes reference to landing page books --- bookwyrm/management/commands/populate_streams.py | 2 +- bookwyrm/views/invite.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bookwyrm/management/commands/populate_streams.py b/bookwyrm/management/commands/populate_streams.py index f8aa21a52..37559f082 100644 --- a/bookwyrm/management/commands/populate_streams.py +++ b/bookwyrm/management/commands/populate_streams.py @@ -8,7 +8,7 @@ def populate_streams(): users = models.User.objects.filter( local=True, is_active=True, - ) + ).order_by("last_active_date") for user in users: for stream in activitystreams.streams.values(): stream.populate_streams(user) diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py index 3b9fd17c5..005d57cf8 100644 --- a/bookwyrm/views/invite.py +++ b/bookwyrm/views/invite.py @@ -170,9 +170,9 @@ class InviteRequest(View): data = { "request_form": form, "request_received": received, - "books": helpers.get_discover_books(), + "books": helpers.get_landing_books(), } - return TemplateResponse(request, "discover/discover.html", data) + return TemplateResponse(request, "landing/landing.html", data) @require_POST From 1006096cd06cc861c1ad5e0283f699f75f9869df Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Sat, 7 Aug 2021 15:40:50 -0700 Subject: [PATCH 0148/1024] Close the span tag for an author. --- bookwyrm/templates/snippets/authors.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/authors.html b/bookwyrm/templates/snippets/authors.html index 5584417d9..81aaa138b 100644 --- a/bookwyrm/templates/snippets/authors.html +++ b/bookwyrm/templates/snippets/authors.html @@ -19,7 +19,7 @@ itemtype="https://schema.org/Thing" >{{ author.name }}{% if not forloop.last %}, {% elif remainder_count > 0 %}, {% blocktrans trimmed count counter=remainder_count %} + >{{ author.name }}{% if not forloop.last %}, {% elif remainder_count > 0 %}, {% blocktrans trimmed count counter=remainder_count %} and {{ remainder_count_display }} other {% plural %} and {{ remainder_count_display }} others From 650a6037a29abb2c47e0084fc91c29594fe61f7b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 15:51:53 -0700 Subject: [PATCH 0149/1024] Trims status text --- bookwyrm/templates/discover/large-book.html | 9 +++++++-- bookwyrm/templates/snippets/trimmed_text.html | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index 81620be1c..fdea582d8 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -1,5 +1,6 @@ {% load bookwyrm_tags %} {% load i18n %} +{% load status_display %} {% if status %} {% with book=status.book %} @@ -59,9 +60,13 @@ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %}
-
- {% include "snippets/status/content_status.html" with hide_book=True %} +
+ {% include "snippets/status/content_status.html" with hide_book=True trim_length=100 hide_more=True %}
+ + {% trans "View status" %} + +
{% endwith %} diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index cfffe0551..f6174a192 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -3,20 +3,24 @@ {% load i18n %} {% with 0|uuid as uuid %} +{% firstof trim_length 150 as trim_length %} {% if full %} {% with full|to_markdown|safe as full %} - {% with full|to_markdown|safe|truncatewords_html:150 as trimmed %} + {% with full|to_markdown|safe|truncatewords_html:trim_length as trimmed %} {% if not no_trim and trimmed != full %}
{{ trimmed }}
+ {% if not hide_more %} {% trans "Show more" as button_text %} {% include 'snippets/toggle/open_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %} + {% endif %}
+ {% if not hide_more %}
+
+ + +
+