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 ba2fcc8c..19f692db 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 00000000..3f225472 --- /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 da717d2e..fe21b58f 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 798d2fcb..fc490b96 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 a771c3d6..aabdc8df 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 00000000..38dc37b0 --- /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 4236d6df..5a9bb2f6 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 38dc37b0..c6e6af85 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 cda11586..71e486f2 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 c6e6af85..eb1e8ebc 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 9504734e..ae9dbe74 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 75c5da8f..f133d4ab 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 eb1e8ebc..2f2b750a 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 ae9dbe74..52e65c19 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 a21723a3..92da0c19 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 f133d4ab..057027d4 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 2f2b750a..ec6e5caa 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 aba804d8..6cbb82ef 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 ec6e5caa..482935ff 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 171e8d37..9bc51aa2 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 00000000..0b37cd1a --- /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 00000000..05ad1a2b --- /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 869ff04d..ae79223d 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 1bed03df..bae23212 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 b4dcc904..169e59b4 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 9bc51aa2..a6d09ecd 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 a6d09ecd..7b20461a 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 21e71ae1..78b03436 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 eb146f7e..c095faa5 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 259f06d3..753691fb 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 00000000..eb146f7e --- /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 7b20461a..90613191 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 108537cc..0dc3f8f5 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 2ab38a43..9684a68f 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 90613191..ae60a769 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 ae60a769..3136803d 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 3136803d..d0937cfd 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 d0937cfd..a98da13e 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 753691fb..7ec7ed9d 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 bae23212..eeef1d9e 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 b38c0e67..fa5c73a5 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 a98da13e..bce3e5f1 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 4af8e281..fcf75b04 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 bce3e5f1..2aee6d88 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 04f6bf6e..f8aa21a5 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 00000000..32495497 --- /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 00000000..57cd8499 --- /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 c2b63bc1..0b583083 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 cf88e987..74eebb96 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 d694e33f..b1deed8f 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 c2b63bc1..1dd4c0ff 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 289d6fe6..7a458094 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 00000000..bad9028e --- /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 16ab305e..6a15f0fd 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 3db25d1f..5a4495c1 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 6a15f0fd..fd1fb438 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 e39d3410..a18b125f 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 df76d8e1..b1b893b7 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 8dae1d04..0736eabc 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 0d5c1044..d22dd71a 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 93026991..2f99a75a 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 73133de4..82cd4a7e 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 d8941ad5..893e7593 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 3f225472..f1c8e7c3 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 315733a3..ed5d50d0 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 33102f98..21b6bbaa 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 0a86c486..ccfb4c90 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 134f419f..b285eec4 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 84091fe3..80b6af3c 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 476956b6..5584417d 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 353f9d12..5eddabff 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 80b6af3c..12224517 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 ad615ba6..23bd8e1a 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 b7941826..ccae925a 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 eb146f7e..4a757ef0 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 22d44c87..c6b3ea84 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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 delta 7368 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 diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 3125d147..5edf43d6 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 8c36a2cb..ce06013f 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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 delta 13433 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\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 d29afc1c..c4ca623c 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 a52542b0..f74dfd4a 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 e11f024b..b7736822 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 020cc49a..fcff9352 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 00000000..d8365eaf --- /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 a49a7ce4..cdfebfd0 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 cdfebfd0..4e464b3c 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 00000000..b5ee7e67 --- /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 17fcfabe..a10f128d 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 7eccfd65..3d39b9d5 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 4e464b3c..2f155538 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 a10f128d..180191d9 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 65cf97e1..780f1d17 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 3d39b9d5..d3e2dad1 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 3001c86e..d28166a3 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 2f155538..0a966971 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 ee7a96d7..c080e3fe 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 8a38b808..666c3e02 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 d28166a3..7a46ca57 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 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 delta 7413 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 diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 5edf43d6..b047f031 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-04 20:40+0000\n" +"POT-Creation-Date: 2021-08-05 01:33+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \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 ce06013f..153d8b9a 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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 delta 13514 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 j>HT+Jp5Y@rsVT>HB##)K>9;W|bJzNOdm3+8lk\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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 DvSMj) delta 13937 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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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

u}4WqQBtflA*pe)b9{Hy2?$PJD0E=j&CoD}Mz zIE8YClABVQqEA3I`u>;pnyBj{^#gcBfn8BJpZr2f7A5;COFbX=b+dc_%)$O^lKg-k zld^kZJvyXP>Qm22S^BR*@=&iqZZxGf_2bx>(u(>KN?99R|1nUOd?RwYzHxCnS?mpU z{$1!ein51>Zz)OC-?UDbY41(lkHQZ^r#Z#n+KONlr7it8lh^eU^{?>(B?tBF>kgGq zD90#?+|!D-Q1rx-c$X4RP?=;VenIl*H|4-zD7UyF-UeuDo+Mv}a+Y{CUZ=dwJv)gDP+wsEem56kEcp`j zS&95b{?phH@Be`)=t-(6WfIMsu>z$q`5}}-GH8 zm8^eX@}H6$MfriEt3A2J*aBblW_Sl5azit3z*mIb+=mXuDF2X;u-r83bCx)qw(M&H zm4?JcDY>mLKj0l-;w{93us@|YWei2Xf@EJW>oZV_@(mrsEIW-(OQ{dR>}xXho|Mic zZqfG@tV%qcx~@7d&V4*#xym?<5@T^UeAVjeo}2qUUz6xcWdvo`zZzd5E@W{>I+r5O zzIIWWOQ}M6gFd$@jjg>8_4g@XP_nQ0s7G0QMUq>s;WvE-Mq0;Hmi!P$P?EXfyyd3R zXA||(xCMRj6T44co>T8dnN4|%GLd_yP=27U>pb3}{6xJY`AgLQp@jHw{!^%AU++?X zPH+ed(^1zP>gBCZUgBu-EwLhQwfu*es?J;u$mb*e)(xGp)NfL@QF76ifx4zr_kIT^ zV^K@)rQT8vTw_hu=h6NZC4su1cHiR zNM8F+Z0{%U7Q>E7dJhol&8;l)HU42>5GpkBgl8KTrB;@QSWAP3bC%!c5gjg zNZikdzrn1r7kz`+_ zUYxoXDR~0jmdJozb5m%$W zQLpoADq$oik$j)JuAit^q_m@6pEg|sT%0e-cP6)rcq(NcWgj_R-A&c6SiLp=VfB}B z0HwLb-q)!royX`7E*~1gtTBN}+EH@a0@PlPQjPYvtf!D2=!wKjnbN(AU{WN*fYgNL;6`YXlxw=luI1(jw+Kn2Jm>luH$w?h5gf~eZl{he>LCWaFkr4wEQxl^{k4jE% zSUM$jY*ONg*m6;+iTx|2lx|d|L9DtoiWoPNhJg_&sfnrMQlgSlDx|L+7MotPUSxXv zVKM2W2S;YMA2!@Sdnx`AS*teQp0zc7U){*evtwdH0<)IwxwGuUTl)`ZKJ;|<3%#{% zxs#Q#{bt6l|7&RWx^H;nIcskpJox`uSJtX^Ss7bz?>um8&YrAkY3Uu;N2KRnQ!>5y M+MvvN>xTOL571!SLjV8( diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index f74dfd4a..d9921655 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-04 20:40+0000\n" +"POT-Creation-Date: 2021-08-05 01:33+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \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 zcmYk?3w%%YAII@yvoSUsvtcfq+s16jeImEHGq;T;nfv5^zs4bV=8{p8OOg^2mRu4= zx+o-(a;v10D7mDN|LgrbpZy=st8>_fk8`~BPtMe;6p zI0pGSPAMD`?l_P8JI=mXRUKzzO~)CHZ{jR0UCVI_;d+e69Tju0lK3A+VpMI% zX^f9yM;wLK@eqbOj_ceaC`KV~9mk2mQrHd~VriU@skjlfrUzE9P}gyak~hV2*bU3# zB#gjSSORw-YjM87Vwk6%SQ$$^?k%tx29OWJa2#RI#6a>Dm><_-2-kNu66C{oZNPrZ4_kiJ@~=@RoX; z?Z6(?#0OC0K0z(~6l(lWs2#h4`V{<&PhvnLZ(Ig0As>dC?;#dezuVX=6hp17wB_-r zJFJdcU|rOOTcXCLp(g5s8aEI%Za8WonpX>6f_hXdP&>B{weZcTes?c{R&vn%8Y`3k zjN00;Cf>mEs0&s>UGOo~+g%T}uy&{&>yBFB0Mxvrtv<`@&!f&;gM4sYX9q!53fC|i zOEvW_*Z?&_GHOe^q9*Qb`7qRlCt5xSb!SV>b*KexLyg;qTKEyvyeF`zKL3{pH1S>3 zz<_4n7ezSgC8>fXF&VXxUa0YdQCm0xwKLODk6VGR{{Y=63ZD~b z#XqC&B)Yk`l@(DhQ!Ug>)Esre6x5xho4w3|s7EjY_0{ZJeHjLjuR_i9Dr%n1&Dnpw z3_B^v&oD2ZN4*O_qVCkMh4<`2F@`)6b)mYb30t5R+5xp=y)Y2Rq3(DJY6lluz81BB zw_EW1HPId`e2U7yLQV7o>Q4X0KzxY0U|>sc!J(*ndDK?NqaI~#)I80wGZLi1+M4fB6J5mocnvkd9efG{+jtk~gWCEbs5=~w8aD$|FdKdE z5^5oSZM}sT#=QFcmnYDPm3#%>b}T@iggPM^wU92TN75VhvSy+dJQ>U35-f;0s7G@E z%izbTJHCuM{~8v=o65Pq^N>Ij1+?Rh#wgS??2Ovt4Ad9UNYsKBqIP7Jxxw6u`pVvg zn(qjf!iyM;_syX8-p)m$s};o%=ni91TVD%x;Uv_AZBZBQiMpeqn21@Zh3rL*KZHSe z%JPfm4b&a`r+6RVP}Bmer?CI=1kEYv4o9FakcFCPvklyd+QK8K1%HLw;xib67g2Y3 z4K?mx)cJlLyafhhRq_bb`N^moZPS7M*LQpe3ZXa<^%hS+-Pt_Ug_fcwd&>8!-XAuRs2ynS5@^LeQ5PJ5g>X2A;#91Ni%{d zsy9&?)LR^fT3}6Fg!M52KSPbbWB!NQnZPvf9Vv)9FB)~dSS+K@e{BM-JQej-Jizj4 zs4ZQJy6{@mGuw>e_^#EDpe}S8^{$*nT_8_aZ$V+Gd5WVyR>YxL8C`ABiv;o&)E&Hu zVYnT2;z88Qb=>?Gb)idUP&ej;Cv{{0s}Q_OK^Hz| z15TqB@I7j0Zdkv6x;J4#)XNlw(HM`~nKr1MN<%H6H)`JDsPW@bk6;cK!$s-rzXrTc zK`Y#919qWSy5H)bVg&gK^B2^44^S5h;E#Qc4@X_7G-~G(QS;VE{^K;`9~!?JwKJPt z0u9`Yk@yMf4lbZh{0;RDc@q<{On2@Q+nFz7Rq`J(84L5%s5|S5MR6GFk<38-7QBG` zo$KUSzk7#3TUW4$_c4n^ZBZ%I9hOJm=Nq-4>Shw^j+>&!wL{%`D(dCzhZ;WtHEz1) z3sB>hAvf+iuUW@-)I@txTXYb$urDn?i`uCx<{i|;{!e=s3PI(OsPBsy)Q!Yq944X` zlxFtC!utGY66je>L_OoVs0FM+ZQT~s9UVZuj3-eOUB+0vj#^kmPwxiGVF~hh)O^XP z`MRSPI1sf1qp+hs|IZQB#*^3%gEII%z^+&WcVaaDijy#ZFTQSZ23E(nQ5X6iHSrzP z$1||E_dmHLpx&7&s2lkd6Yw0mT6s_(Z>uBCvN(!*0`ht|Yps3{bti#+y_d8o>cTOo zdFr6Hycx!08`Ps1i+Z$^u|3Yf6g<(F{Z}ETpLeIj(2sl_YQoo$A24UT>DQm1YVs~v z3)iC_#TnH2AFvW$w|cPw-a=!LZ(}FHoQ_?{PY-at|K<~)={@Vds5=~oF*p+ga0BW> zn=v20WA%L)NPf`r&rsuzBcDj;jO8^4dgB_P-i>D13!iog@)7LE{P;08%fkeyXB|F> zMc^XTvkM>W{ecmOny4`r!0wj!M}6*HjKgJE4fmmT?03`+mL1~#J>XU&(A(b@HLyFD z!uiN9I&WYl3>oVE?AAejQFXU`B&vTo>Rs4xevO*vH>`m9hVhGu2{;;idAiQmR%kWc zdq(?k0s{(Qe=N_#M?w?jM@O|I`OBG5BD zh?@8)YNcl}3@@WDd`?!?CvYw?>`c(ehrXk6k8e{6U<8r>wurIB%!Aqi%e}IQCyF z8&5$Cm}wnZsCqW)0|hKqtmx z8LWj7*afx1XUq}ic+^Bw%?0KPbA!3VJYar-B{}a~tc$m?D!Pe$*2)v~KwWT}IR~|{ zMdm7V6KVmwEkA7eN%MQFU$gukYTo=4y&DTfonO(@b!u3l5f-PT9cm}~qjq8@YJ!!h zEnR2%o0f00d^hTj4p@HOylvh`UD%(mRoz$^=F{(g83J|0qApYui(!4McQ!LnCl0ZE zk~zm*hFb7C%XeA+5$a|9&g$1tkK$iU(&s;NvUlN*s0(yMEvUaa%IYra?O%vm=sMJn zY($OUhPu%EsPB_6(I3xZe!Pe}?^o3LKhXF4f8RQSp7lP@VWj@aIwE*INJUs0HVkpP=uH&H67t%l_*^e_7!n>JEbW(CW^jQCk{^nz$jVKN&S~ zH`MuqQ45%Wg>W{O!{ye$8@15GsCiCVer^i;udVr=g1n9T5%~}GO_+D8cS1|l%b8+% zra26?ps}ch%r%!={Z-3%q8512{L=a_xCGjg8>p4tLrvtz!ZdLxDlcbNGaH~LY;Acr zvma{bMxu6NqSfc3=3kDnxC*PIdx)SY!7UpQG|k(pFw})(P+OgdZLtaJ0t?OMsBx=N zzX_YL8@`7XF?_n$pM-_UTc8$_?$uoWpysWCx`DjY1rW0twEYyXw&DYI6SdRJ^s6Vy-KuuhnKMXa# zA}X(Ed2=(}>Vr||O+YPh9qQ+PFS->7E)(ck6`1ASQFV+WuWxx8YJnN3l@G9dnDvjf z+_ikRwUk*0KK9W>*ZP-WRpt zL6*-#?MN2t`{O0lLf%Hb1D7xmZ_Kv0{w@Wb@X!VX&+%3mg&J4~^^!HTygh27RLqBc ztUd_!X&H&y@>!@m-HIB21ohQ?1~u=cfdu&oezT6htm6T8pq_WGH!u~oz^70faUN3CEU z>ikuxJ6Mk;a5GlI!>AQs#~{2n&%W#f=6fAQP;Xx}YCy7?V*Tl;3-rfUI0O@LC+dPf zTK{k64b(#KS{}T>yG}Uj8N@8$VQWPVDCl$08ns7#Y~U!F=oXBNloS zmNF}&&aZ>&Z-H7+d(=YHFb>`E1i=Jr%`N60^JCQK=p=^Vb=1W7F$RMddFLmh`s-WX z%1lFz?}J*%DAWy3L>A;aS=O=4d>IQc;8pZ(Eoy>Y<|n9$zCkVg0&3h<>%VRFfW_V& z7r`F%N1+xt-kgQLFZ*l)t!O=J!go;@IE4B=Jc8P)d#IPL{1SWlFp+#GHpfe-Z zd+$;s)Jv9b`50_Oz7RF;DC)P|xkR7~-b6j4e=YZ0>iw}6gj!gL8D++qwNMi_!6Mkr z>Vr@_Gv1tT^#$e%bhXtR2(*B0s4d!M9>!4elc-O}CCl%d!P#DaDGZ}O0d>KKsCipr z73_?-do><2IClOR!?)}eN890jkJ=C+S`hs`oZE!ewUyR3-=6}{- z`9*IhnxeiTJ7XIhhfm>$7>T7t#WENlPh@=!b9wYK`(m)pF-u^P~-hpdE@G# z?xZP3U>()1fc>bK=pzYkaTizD+^1gwZXBU>l{rEV3hrWN=6S>wK7=wA}h^6Hodnl}>U6vF#&{hz4#0K~W zE~LFi%&XwMLW}d`9~}Aw=zq5x;LG?;!2a|#q1K)DtLnUeP9c(3G`%p#Xk}?<$kS-r zi3YR-v^<>L5MyY2>B~KSC#XQ*<5r6%E=BDZT2o>j^&c6pyprX*zVEX*5&e~L6sEn% z0A5<(*8NG`nwCHwMH@@g(U!@F;Wl5!pEzcFoX&V2wNn6_(#p{MX*!DAqUPk`{!3E4 zP4Q>iRN|f(%76=~<9$16jj38anm&dTXwkH)G#y{i$}w&)ZnyDz7j(Sg;WWW%)>k7B z_y0PD|0wLFeM~D(yFkl5_(Rk=NuJ80mJ;i2??K!h`K@uDdt~fM^4z1A1w-iPQ|H9s z5n4l99rE$C6E2Cqa`Q9cc;ejSAA+m2%GAHftrP!6{1^2`7?3*{FOfe^|8@M$>Q%@; zCf45xE2%$vWRd5m;QmbT0_`yy5R3Qd&@bI&T1_TtV}0Anf1(YbrsEyz!)T4j7ulHE zm`LklV~!DDr9DZ07j?X1ZqxG*rei;aCA4RVd($$An|WjZ|IZ;rMX1No)?2k9V>b~e zP}7k_{t=F{T)V4d9&Hb;G5L?QFKD-XeLVkU0)3rdn+v^QqC;w)NJj&u64X`7S z+ES}eqIRD48+oSHBCsm+oT0wjYP*OJ(H^5Mr}jOqxjuj02=39MID!8-{qzqzN>l$T zH^H0aX;_^x{}30z6XahJ_r*c9=ZQbSfw&Gg(sX=H{yzSW0kkp1y1uiOmTnhqL_CYm z&(y)Onbw@X>%PqUM+&U8{2CUtxSzR-^PixNBmV^T^{!(y@hLBKwi0tZ;T#|+#|7TQ zg|q-$$b4^r^8=&4roBo2IjuJRAK@ixBeGA#m2`_y38B)G)`WNxPN#PXO+VVX$3^P7 zM=i$HB*~`MhFC`mrjl2twXoU`#DCN3SpF(;YsTis6dH%C|I_0Cj~hf)XnpL25yT~l z$9aQ&;}-MJ!H?ukeO11+85d6b#PWFJyTrXMZ%wYFGwmSfpYvrr!eS&((b=EEr?gGv zwP``rUcw%lSc+#?V1`A706?4m8K_5sd&q~G@ny-XqOkzzY$ z``O8hL|!9P^Dz8!>fXrpMkM=yej*58r^93(GpooVESX`%G@qPh32BbX%I zPI|&>LF5_4Q!L*>{=mi*#<^C{AwF&KA>zL+{>;XXw!AKRK3YFoH5S3)I-R}1*+p?T zEwAOB=p@#VdyI3Q z!49-7w9jczGPajpcs6;wol7{#sYSAkNJmlP-n5ytZ^$2F5GK*`(sT^;@co;7g`JqV zyiNWu;|I|a$xq>O`Wq7;CGMKtsb;u4g-FM9w1V_(B+rK-w3@{4Q7=R5K>RedbmA_G zQO9KuryYHv#A|4o#3g7m7*~(Bo_3u2JG7fL9mPCcryc`4GC;?xv^QyQ(^k{opgxvX zmNDxv26a>*zJ(1ef1Ny;yfpc{Sk&ru@jLo-RHGH5{Y1W*w%AwK>&Ed6$xzz!#E;Y3 z6L+GuB)&-N$wU$OAvGO-4KxCA;X z(CYdk9v-z03_eRf!1}LYe~X`_ewsL+jnBppY3=O-4~a9aueqJm6O-v5iS=z<1lFF) zz}>X@wEeUNcEUOHOKLjul6SNdtLK!hH7{?@@p^BD3Z z#STYmcE>4-iwZbS;~b8YH(FW8iK*;3X&8%dVg|m1B@-Q|48~(HcE{Y9hG94nLvT4J z;m6n-f5(bg|7FJsbR3T}l1eCvX&87SvfD!lv zgRy8;$0>~Q$ef+#7>biI3YTF#*LU_(NhR@{nNrPhh7x~+?J%jj4s%E%e2}nvTP!I>BZv`VrT{oLt{&KqUZMpg(rC4!tZMXz>V($6-$T zO-AmNGaK{bTb5sexro;xTkLGHc&~W`)&DelbT5CTk_Yc$C47RKVcA-alMfS6D`|i_ zu_@}jj;M+BMNK3Xb>TGBg(sl;&qIy79OLo0<^QS0{%hrVYr6v$K@Aj(x|iipC$vKK zn}XV*1*i+XgPQ0X%#R&&C7P#B$YP{|iwGspHPL0_s9_P$#rN z?Mz$L4!nvQxHqcbVAM{GNA;hD+OfA#Z^LTrj2lt?e3F<;$S*FC*u9ocdIFvz(4t z9v5N>`~r2spHLIaLT%|&)Bt|<-M9ei!o@8vi&|L~vk~gT$*6uQsEMayklz2%RP;eI z6E$!Ks^dn~2gawUXXF%yVHRp4z75>|`A`!rhT54@s9O++e55!vP+LCIoQUc_69c)v zvw(^&_^!D{4a9rU2altk+HX)haTB$o$EXSWHgqqL-z;jDMzvQ&O}LiDO;F<}qel&W zs1(6rs2R^eUp$1`%44X9={wXzbQ`sz2dI@iGkqJmaRBPPVARe=S-u+j64ynI)3_1) zuYp>V&_mP(^{@@KcryABFGf8R%TX)Zg?@M#!|?>_g1@2$evX>3e`9y&3ZWlydDO}i zQ9IeNG5fDXM-rMyKh!|OEuLiYY}74ShW@w}HQ-Lv1^1#BaMW|2jhaZF=I$*ijJo$FP!mqT zNNi&5gHY!U$2>R*b?fG0ajx&AQ_&7=L*3(DsE+$BK8_mrG*-czm={a5a3@|C^}$pd zb)hb(9U5ScFkeT#UDHtGEk#dJDx0Wiz@z4Q)K*?YP3SHL-~-eSWn&+;V}7Us3!yF? zhsCivmc!1diOfLtUw|5Sjm4WOF}C?h2eM!HN$6E2J^RaS6B;mfzGIb#-jR7 zLG9pD)Pz@~ws<{i;+s$l+=c3Q7P!H6AeNh)2hFaJ})U&Yw)o&eYybn=3dB{V>yY=RIjHlrmYGom9?Cn5ZFack} zny3ji!&2B4wX(_PEL8uuF$kBVCb$VTkxx*!&ht5yC@QB=579%^z(H-@r#=F;BV|!1 z#-j$VhFU>AT!@WP?cbv&@)K&JS*U)GPz!yA+M(R-ys^hAL`5A-p)Oq6ZEzZ(K8V_& zP8ekE<4_lxh1#J7s0psO{D)YQc$>AK#|p&1U=W72cPCg5bL#z1q@r)X+8B$SQJ-*A zQCqeQHNmy!Hq-~z7pRq9L+!{fsE7Cu)C8Smeg}d-mc=Eg{s+yk(MRw987c+vThxhn zP#1iFdfKyhaAzKY+K~i{TcEbI2kOFuQ6E%eQR7Xu{8H2{Sc`gA-bamp0zI114^%YJ z&zJ*$$07J9YGu7Ux(-40AC38NBI>;PsGVAAZa`h=BlA4!yuUF&`gC${X=o?*Uo$C1 zLKmux8mJaVV`GfNRMY?~tbHwN0-I6ybg#9aLXGz=>RGypCGaoQ&V=$?TsswsdZx;E zX8$#CO%ghx0qPdC$58BwYEMH=@O5jShMMRc%P+=Y;#KB$)Op8H7dnmVe+6}&+o+v; z;-R8}{kypTP{@ZmVIXQHV^JMvU8n{c{@>`ko&P5{(?=hFkgwXHA~f&rHAW?ur9Z z{R*R29)Wr|D4fT-f?D}-%TGiNGy}Cm^HCGau=ssc|4+<=sBurB zCicC>*H8<&i++0lA5e)V@dVW|@>SP3)WcO7bt@X7?r}0|0)tRHHx9L;xv2i{qQ=>V zrExcEVpmZM_!SG|Ul^?SKd6U0U^HsRiKrc@gM1A*tuPVa#pZY(IoB!qn)_Wb1xpa` z!0~tv_13gbasN}x8>oqIMvZ$A^?IH`eg8O*spw&8+S6UhVk}Gi0cz&wQCoe@yoV!* zA0y9`Gq{)Aegw5MXHXC6PpAvuMU9iAxBKkm!!pF7z1e@=i+UuqHBGPuw#JsY%Hq2i zPh6u9pN2RTHQ;d60w$U#u@!N6U-!TH3`5BI;KCj$^U$aNZc)kA+ZAXcZ`o5!eRx z(50EH&{yyOQ7YPslNgBCQTOT(%!N-e0DYN-@&(KyW`r4oxY&$04A=JHmgc>-g3zZ}K> zd!K4coJFnpB5GpyQ1|kw#RW&Z7m7fgR|&NP)le61jGAam)Ht2601mQt4{9f;TfAg6 z`>)q8gM?0agcC5&7)yh z$U{XlFM%4cw8iC77fQ6a9%_QGpib=I5x19WqawSI~PaEq-coEY!iVDXO@->~=|me>3L&=OIvyC=q(@u-9?H zN1ad#^>oKuT+iBDq2B8bmLF^RH!+<2T+44ZccI2PJc0e!3NDb)g?_dUcTh8bYz9np zU!MrnMB>bOT+lkS?-#v$-8L;oTl8n#l?CqBY#I_$g|FIVZV> zpiYcJeV|l9U8pWZtZssGaG6Ie2EIHnf_x8)Cz~_T zyM?F~WuVSqkM(hf#g9?9A{W2Qbm5|?ehH|2ee~n{P6sNwm))&HKh#4r28-hY)J|+Q z_n1df6F850eJ`VSC<}Fg`(}p?#TKtIcUb-i>cn%X z2|h>t4hWs@{&cH{rHK2X7Bmlw;8KgXp&#)c)Wi=?XaAM>nuJa`jfyW>e9hv!m_Ysy z%g4-c`^BT~Wi`~+CZnFEKB$F^Mt_`Y&Oz-=I;wrc4EA4@OcH*$A2s8{7GJfFS*Q<` zKT#9OJJWpzl2GThG?P)|b+h&Xs0og-_H@)lms`BiLq!kM$LNpytl==~^*Mntcoj8J zo>^}HXw*GVL`@(Gb$(;Zx3YW}Y(+lB;*U`i{1mklo-eK8TWk0cHK98eKS9mdf3|yK zDC&Yys0qedTnE*!k;NUXy}QN3&9PXLejc~okoH_2lU~-~% zA`-QNW|#{*S=`f1#VGP`So?eCht|FWHU0r?qWAwOm9ixA&vh?Y2i2jm*%GzVWQzx2 zUgBY>TQb4oWvI7e18OJsS^lJX2{mq(#rLJ&|7TRRlHBv$51fLiTktY!2O6LTY>pbB z8@9z>m=`~>{6UM4p?2~D>b%>Qe`5N-<^B_|AbPZ=uTaszBTxg5GpC~lNVoR2s0nRE zeKKytXgrHL?{72Ld^Zj;OQPPYiWq>+Fc3S>XaB>g3?QKaW?P4)7OywAVIb}MP!m0g zTH$%rgt9FEoB0THlm7?3JG;O=zn~d~8mICCd;e>YP{$_Lp)G1cJy91(#cntTwSu$e zRSYD)kD8G4wtHRy)CIz^B1WTjsuMQBN#;=xm2xEVFXWdlCZRrPrlTIFm8geohsEDu z9pc-ler3|#2_&H|*cvtAju!X89K?N53mRySF+J0)@-}L~RhS>QTmCR=XU>|JEq}{= zh}!Dxi`)qWpmwOB8Hw7Vil_x8S=`yx;|#FGILt?fS*QyxM-99V<8Ui#WfxH^xrT-D zK5D|b7rP56hH6i+I0^Oj+ri=?sBxxZX}$k*sOW@ks4d)w#qcW(#_OmHJVEsfSmJ&j z6v1}H3z(drE|F$@Ag?mdv zus!*3bCh`u6UmoY>7JjAx`o}a4faKy_o>AJ8E*d`8SKA0E+(OstVV75Ce%a@SpFy` z5uZn`D0G$UF!Lx@BOkfi{jJvx^(+m?Se$|yZg&0QM4Qt?7)PUPj{q|xud~sB;O7840GNuR5)3Y-UrLiw1l%o3=ME(y-S?U`o zIttnVC#gT6?G9GJAT@G~qduRKK>3q+64s^Mqzv%(aQ}3$dPE%t)Yh}J-k;y4iEmJ^ zgm2)o^pvt;nx)g5OcLcf_4AbG45_0PWia(Z-iZI5+$=<29rY<4tX`0QS1AjqTm8c{~kmQ1-s89~`ju0eL5lB!e=lF-r02J26~BXxaB=qNy`PM?R~i2semoP}$x zE;`WXKa}0n?^E8VRJO5io1~ncjIGC(w}d-w4Sg_zhL=h6I6HpS`;yy7$)mm;JFIUS zcBgzxZlJft{S!t`pAbHrtK$~sw713!Pg`kxn9J2WOdx7&Tn|{p-+^K#5$V0c>m|iBy!&S|GPDgp|K8SJ#l3Q zEN`7fQ{rOQZ!NxLlh{k!Ug9sT?`Z5#TP(R4N-^SLlvdQE$j_mEhH`;2-2L&uM-q)X z^aa|CdLpGak7uaoGcvxEL{6-_=w3)J=g>&QkugEEa$oxV*dIt~--(6_OU z62xP%m$iRv?JrxbJ_D&|)8pww<0cZT(Vy}eV3)SctYXp z#e3`~A5X16j>NAiXQ}JZhg@Mhe=zlTD3^76?$Mz!!HXl6c-)Hsk5Keav+U&c>$tWJ za+>%j%8TPFm1x>pTf4r0j$8W;%t!n)rK;sZ==W5Q=Wxnjlt>z1!#tEM%4XssIDt}& z`Y)7Dlz$(OXq!QqO?hzyQ*T3QO}S>tb=1q-#L7@_Leb&*no1wH?v$iMJIVoaUs7sQ zF4C5hlAkhww%4#LzCzo7sryskPyNO574;khg)G++za-vd@gVxQB)&|1Bpdr5L?W3| znPdTyJt^-}*U^9yPpn<4Pbo{ktvHqZX4EmnEbfL*CjLmS0)1Z`y{P0PSJC<^zl!=$ z-Tx&7?-LBcG_`OPaq<2w!`~dVhcVzsmVcFcPIAYI%i*^a9TO=%XnR5&>do+xhPjCA zl3$7MP`XerNxrZ?9=4GPAn^(Hfz+o^KBqh-*3pi79ZG;3IZ?I$DsQ>{gw5 z)OEC_?DN+C?@w;pP7#i^K7$#fIprJT`?~*s(dbLCi;_zH9wnXf4P^zT3gsYW0p-Q< zn7%)}2(T>!4x#9XaB)`S6v}@nf75@x<@@0pN;*03$Mc)s3g7dJ?FeVE?<}9!j3HN^ z`Z41c`H95!aT0ND$}&m~;-jdeos0Kx5`XW|Uq^2jXA63MwWM;z zIr%YOAvXb^VKBL#)O%RJV#L)bI-XH}Cf|^Fyf@?iiL~}dgtINbhkggBU$=2msISod zFG1&Ml3$SsquiptkP=7HQIYnK-Kz5*xj^cl;2cU#>!a&cq7+qyqrJJn+E1Ck;125UoZvh~SHt^xH@n2!=kJqI45PZvs6>N3*R0Xo#-C4#o7sfs6OSRzOI!+D z5SO6LqpTtBME-N?I%ZJjdTacvoVH-ADa1I z!YrTk%WVRE!h4PjPmdcKomr>qqJW(32Mp;mc)-v;nMWGl_YHKKr}j!29R9z_ZOz6P zNgAA*(mT9n+OU+N;k{Evrj#3&I(Trc$h46o`lJl0P%36*O3&D|$l4WaR#2DP;iHDq z&^tVBWXi}hF%EBbz|9- ztR?9;cP`I-`uYRk0yjTg=G<7h>F1Rn{a?fF$@7aO-P$wj=Qr2?KPGcyO~#Ft8*goy jbaT$68*k1@|7K;K^wukKr>A99Oux6RL}tE>@a+EsS24J2 diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index b7736822..5ce42251 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 0a966971..b4926285 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 b4926285..7c15fd90 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 7c15fd90..01ca3f77 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 a49a7ce4..543a8a7e 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 3ab33862..de5e5630 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 543a8a7e..4e48a044 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 f4747971..22445892 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 22445892..ba495089 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 01ca3f77..6b75a65f 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 6b75a65f..bad7c59f 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 ba495089..ac57d8b3 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 ccfb4c90..df89d5b0 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 0efdf16a..740f0d29 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 6f6116b2..51f8b5d5 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 492d0cac..d56e2f22 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 c66f0400..38101772 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 51f8b5d5..3b674852 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 961b9797..4137c6bf 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 4137c6bf..ebe2cbd9 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 ba495089..ac57d8b3 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 ccfb4c90..df89d5b0 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 0efdf16a..740f0d29 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 00000000..dc6b640f --- /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 21b6bbaa..cb6941c9 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 3a95ef7f..de04b7e3 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 41e8911e..7e4a9d00 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 de04b7e3..9c42d79d 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 8a2e78dc..8d893047 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 3b674852..6280f54f 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 3c5d8b25..d75d368c 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 10531f51..e2d67fbe 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 003e94b0..6598aef2 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 13c0ef5d..d9d67d56 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 b047f031..140f91dc 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 153d8b9a..ab56046e 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 5bae4d7e..dbf7540c 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 399e4056..b4405df5 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 d9921655..471de85d 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 5ce42251..40b12995 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 1eaf57c0..6ad46420 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 00000000..76c8c962 --- /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 2cb7c036..5b55ea50 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 872f6b45..fdc06866 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 cb6941c9..08bd87b3 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 f42aaaae..a74e7bb3 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 5115469c..c5edb55e 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 657310b0..516d64c9 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 08bd87b3..94b7b41e 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 180191d9..130889ac 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 00000000..b47642af --- /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 00000000..b81a5a83 --- /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 00000000..e3d73938 --- /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 003e94b0..43b4bb37 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 46bdf722..42e8a6dd 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 a74e7bb3..f42aaaae 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 c5edb55e..5115469c 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 516d64c9..cf46baf3 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 76c8c962..ab0aa158 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 fdc06866..ef3f7c3c 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 94b7b41e..e10bcd29 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 130889ac..180191d9 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 00000000..ac5b9282 --- /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 d3e2dad1..e7036feb 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 41bb64e5..112271a7 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 43b4bb37..edf960cc 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 cf46baf3..fff3985e 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 ac5b9282..00000000 --- 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 00000000..85ca2bb1 --- /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 00000000..00a89403 --- /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 d36371a4..f64b529a 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 edf960cc..dedcf408 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 85ca2bb1..6c9eda5e 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 00a89403..7c0c1098 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 e3d0133c..19c103ea 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 e7036feb..eb8491a9 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 112271a7..eccb7f5e 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 dedcf408..f81be8d1 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 6280f54f..c5d86a12 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 03147744..03875193 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 e2d67fbe..bbafe7bd 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 140f91dc..4906082a 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 ab56046e..e8e3b0b3 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 dbf7540c..9fc28535 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 b4405df5..f0a559f9 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 471de85d..adb0d36c 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 40b12995..c496bb92 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 bbafe7bd..bd4b3b02 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 5cba5455..4811f4fd 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 d56e2f22..6cd0427c 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 bd4b3b02..dc9f5dd5 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 b47642af..231b0388 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 e3d73938..847009e5 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 cd7ea806..9e610bd1 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 bad7c59f..66dcad84 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 dc9f5dd5..22008e10 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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\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 f0a559f9..badfcdca 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 66dcad84..754b4b15 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 a6f3a026..dd7036c4 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 d553c368..38180c3b 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 73133de4..3f7cbecc 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 4d1531e4..476da74b 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 eccb7f5e..15b55acc 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 00000000..9bef6974 --- /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 42aa48f0..f757cec9 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 1361935e..6f480b70 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 00000000..0a419e51 --- /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 00000000..b273d431 --- /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 00000000..052a540c --- /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 93026991..b273d431 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 3f7cbecc..2ca505d9 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 9bef6974..685a4ded 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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 Wyz)FY_Ai{bY+FB%yh=M#{QnP}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 0a419e51..01ef2186 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 b273d431..81620be1 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 052a540c..1318c8bd 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 0cbe6b8c..8cafad7f 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 685a4ded..0b1fae2b 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 f93354bf..6e891723 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 f8aa21a5..37559f08 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 3b9fd17c..005d57cf 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 5584417d..81aaa138 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 81620be1..fdea582d 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 cfffe055..f6174a19 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 %}
+
+ + +
+