From aefb0c9b14e5ff24c120d48a2371546d86edafc7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 24 Mar 2022 12:43:01 -0700 Subject: [PATCH 001/167] Re-consider list privacy on edit Please run ci?? --- bookwyrm/lists_stream.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index f6a35cc25..c40d2b534 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -115,9 +115,12 @@ class ListsStream(RedisStore): @receiver(signals.post_save, sender=models.List) # pylint: disable=unused-argument def add_list_on_create(sender, instance, created, *args, **kwargs): - """add newly created lists streamsstreams""" + """add newly created lists streams""" if not created: + # the privacy may have changed, so we need to re-do the whole thing + remove_list_task.delay(instance.id, re_add=True) return + # when creating new things, gotta wait on the transaction transaction.on_commit(lambda: add_list_on_create_command(instance.id)) @@ -217,7 +220,7 @@ def populate_lists_task(user_id): @app.task(queue=MEDIUM) -def remove_list_task(list_id): +def remove_list_task(list_id, re_add=False): """remove a list from any stream it might be in""" stores = models.User.objects.filter(local=True, is_active=True).values_list( "id", flat=True @@ -227,6 +230,9 @@ def remove_list_task(list_id): stores = [ListsStream().stream_id(idx) for idx in stores] ListsStream().remove_object_from_related_stores(list_id, stores=stores) + if re_add: + add_list_task.delay(list_id) + @app.task(queue=HIGH) def add_list_task(list_id): From 8d266fda4dca59ac106f097d8f4a15fdd1c9ec16 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 8 Apr 2022 15:21:06 -0700 Subject: [PATCH 002/167] Removes unused `related_book` field on notification model --- .../0149_remove_notification_related_book.py | 17 +++++++++++++++++ bookwyrm/models/notification.py | 2 -- bookwyrm/views/notifications.py | 1 - 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 bookwyrm/migrations/0149_remove_notification_related_book.py diff --git a/bookwyrm/migrations/0149_remove_notification_related_book.py b/bookwyrm/migrations/0149_remove_notification_related_book.py new file mode 100644 index 000000000..c976af6c9 --- /dev/null +++ b/bookwyrm/migrations/0149_remove_notification_related_book.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.12 on 2022-04-08 22:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0148_alter_user_preferred_language"), + ] + + operations = [ + migrations.RemoveField( + model_name="notification", + name="related_book", + ), + ] diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index 417bf7591..28c5b803e 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -15,7 +15,6 @@ class Notification(BookWyrmModel): """you've been tagged, liked, followed, etc""" user = models.ForeignKey("User", on_delete=models.CASCADE) - related_book = models.ForeignKey("Edition", on_delete=models.CASCADE, null=True) related_user = models.ForeignKey( "User", on_delete=models.CASCADE, null=True, related_name="related_user" ) @@ -38,7 +37,6 @@ class Notification(BookWyrmModel): # there's probably a better way to do this if self.__class__.objects.filter( user=self.user, - related_book=self.related_book, related_user=self.related_user, related_group=self.related_group, related_status=self.related_status, diff --git a/bookwyrm/views/notifications.py b/bookwyrm/views/notifications.py index 0a7a62002..e081b07c3 100644 --- a/bookwyrm/views/notifications.py +++ b/bookwyrm/views/notifications.py @@ -22,7 +22,6 @@ class Notifications(View): "related_import", "related_report", "related_user", - "related_book", "related_list_item", "related_list_item__book", ) From a2a04da49356165e53cbcd557ad2b9ad2a1e75e1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 9 Apr 2022 09:41:10 -0700 Subject: [PATCH 003/167] Adds many to many related items to notifications --- .../migrations/0150_auto_20220408_2236.py | 128 ++++++++++++++++++ bookwyrm/models/notification.py | 41 ++---- 2 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 bookwyrm/migrations/0150_auto_20220408_2236.py diff --git a/bookwyrm/migrations/0150_auto_20220408_2236.py b/bookwyrm/migrations/0150_auto_20220408_2236.py new file mode 100644 index 000000000..bf1c30487 --- /dev/null +++ b/bookwyrm/migrations/0150_auto_20220408_2236.py @@ -0,0 +1,128 @@ +# Generated by Django 3.2.12 on 2022-04-08 22:36 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0149_remove_notification_related_book"), + ] + + operations = [ + migrations.AddField( + model_name="notification", + name="related_groups", + field=models.ManyToManyField( + related_name="notifications", to="bookwyrm.Group" + ), + ), + migrations.AddField( + model_name="notification", + name="related_list_items", + field=models.ManyToManyField( + related_name="notifications", to="bookwyrm.ListItem" + ), + ), + migrations.AddField( + model_name="notification", + name="related_reports", + field=models.ManyToManyField(to="bookwyrm.Report"), + ), + migrations.AddField( + model_name="notification", + name="related_statuses", + field=models.ManyToManyField( + related_name="notifications", to="bookwyrm.Status" + ), + ), + migrations.AddField( + model_name="notification", + name="related_users", + field=models.ManyToManyField( + related_name="notifications", to=settings.AUTH_USER_MODEL + ), + ), + migrations.AlterField( + model_name="notification", + name="related_group", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="notifications_temp", + to="bookwyrm.group", + ), + ), + migrations.AlterField( + model_name="notification", + name="related_list_item", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="notifications_tmp", + to="bookwyrm.listitem", + ), + ), + migrations.AlterField( + model_name="notification", + name="related_report", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="notifications_tmp", + to="bookwyrm.report", + ), + ), + migrations.RunSQL( + sql=""" + INSERT INTO bookwyrm_notification_related_statuses (notification_id, status_id) + SELECT id, related_status_id + FROM bookwyrm_notification + WHERE bookwyrm_notification.related_status_id IS NOT NULL; + + INSERT INTO bookwyrm_notification_related_users (notification_id, user_id) + SELECT id, related_user_id + FROM bookwyrm_notification + WHERE bookwyrm_notification.related_user_id IS NOT NULL; + + INSERT INTO bookwyrm_notification_related_groups (notification_id, group_id) + SELECT id, related_group_id + FROM bookwyrm_notification + WHERE bookwyrm_notification.related_group_id IS NOT NULL; + + INSERT INTO bookwyrm_notification_related_list_items (notification_id, listitem_id) + SELECT id, related_list_item_id + FROM bookwyrm_notification + WHERE bookwyrm_notification.related_list_item_id IS NOT NULL; + + INSERT INTO bookwyrm_notification_related_reports (notification_id, report_id) + SELECT id, related_report_id + FROM bookwyrm_notification + WHERE bookwyrm_notification.related_report_id IS NOT NULL; + + """, + reverse_sql=migrations.RunSQL.noop, + ), + migrations.RemoveField( + model_name="notification", + name="related_group", + ), + migrations.RemoveField( + model_name="notification", + name="related_list_item", + ), + migrations.RemoveField( + model_name="notification", + name="related_report", + ), + migrations.RemoveField( + model_name="notification", + name="related_status", + ), + migrations.RemoveField( + model_name="notification", + name="related_user", + ), + ] diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index 28c5b803e..7b8059e0f 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -15,38 +15,25 @@ class Notification(BookWyrmModel): """you've been tagged, liked, followed, etc""" user = models.ForeignKey("User", on_delete=models.CASCADE) - related_user = models.ForeignKey( - "User", on_delete=models.CASCADE, null=True, related_name="related_user" - ) - related_group = models.ForeignKey( - "Group", on_delete=models.CASCADE, null=True, related_name="notifications" - ) - related_status = models.ForeignKey("Status", on_delete=models.CASCADE, null=True) - related_import = models.ForeignKey("ImportJob", on_delete=models.CASCADE, null=True) - related_list_item = models.ForeignKey( - "ListItem", on_delete=models.CASCADE, null=True - ) - related_report = models.ForeignKey("Report", on_delete=models.CASCADE, null=True) read = models.BooleanField(default=False) notification_type = models.CharField( max_length=255, choices=NotificationType.choices ) - def save(self, *args, **kwargs): - """save, but don't make dupes""" - # there's probably a better way to do this - if self.__class__.objects.filter( - user=self.user, - related_user=self.related_user, - related_group=self.related_group, - related_status=self.related_status, - related_import=self.related_import, - related_list_item=self.related_list_item, - related_report=self.related_report, - notification_type=self.notification_type, - ).exists(): - return - super().save(*args, **kwargs) + related_users = models.ManyToManyField( + "User", symmetrical=False, related_name="notifications" + ) + related_groups = models.ManyToManyField( + "Group", symmetrical=False, related_name="notifications" + ) + related_statuses = models.ManyToManyField( + "Status", symmetrical=False, related_name="notifications" + ) + related_import = models.ForeignKey("ImportJob", on_delete=models.CASCADE, null=True) + related_list_items = models.ManyToManyField( + "ListItem", symmetrical=False, related_name="notifications" + ) + related_reports = models.ManyToManyField("Report", symmetrical=False) class Meta: """checks if notifcation is in enum list for valid types""" From fc3b609adafb57f37f7947bfa448f5c1ec3a635b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 08:42:48 -0700 Subject: [PATCH 004/167] Use general ratings rather than privacy filtered The original system customized how a rating is displayed to every user based on the privacy settings of the reviews and, relatedly, who the user follows. This is cool, but the query is too complicated to load in sessions, and the initial load, which isn't mitigated by caching, is too much and causes timeouts for many users. Also the cache clearing wasn't working correctly because I put in a wildcard, which does not work. --- bookwyrm/models/status.py | 2 +- bookwyrm/templatetags/rating_tags.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 1e31de774..f37076b5c 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -374,7 +374,7 @@ class Review(BookStatus): def save(self, *args, **kwargs): """clear rating caches""" if self.book.parent_work: - cache.delete(f"book-rating-{self.book.parent_work.id}-*") + cache.delete(f"book-rating-{self.book.parent_work.id}") super().save(*args, **kwargs) diff --git a/bookwyrm/templatetags/rating_tags.py b/bookwyrm/templatetags/rating_tags.py index 670599e25..cc23d3308 100644 --- a/bookwyrm/templatetags/rating_tags.py +++ b/bookwyrm/templatetags/rating_tags.py @@ -13,10 +13,10 @@ register = template.Library() def get_rating(book, user): """get the overall rating of a book""" return cache.get_or_set( - f"book-rating-{book.parent_work.id}-{user.id}", - lambda u, b: models.Review.privacy_filter(u) - .filter(book__parent_work__editions=b, rating__gt=0) - .aggregate(Avg("rating"))["rating__avg"] + f"book-rating-{book.parent_work.id}", + lambda u, b: models.Review.objects.filter( + book__parent_work__editions=b, rating__gt=0 + ).aggregate(Avg("rating"))["rating__avg"] or 0, user, book, From fb3c7205aff00dc3f636336dadc2fec8a082b1dc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 09:17:51 -0700 Subject: [PATCH 005/167] Updates unit tests --- bookwyrm/tests/templatetags/test_rating_tags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/templatetags/test_rating_tags.py b/bookwyrm/tests/templatetags/test_rating_tags.py index c00f20726..a06ee9402 100644 --- a/bookwyrm/tests/templatetags/test_rating_tags.py +++ b/bookwyrm/tests/templatetags/test_rating_tags.py @@ -40,7 +40,8 @@ class RatingTags(TestCase): @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_get_rating(self, *_): - """privacy filtered rating""" + """privacy filtered rating. Commented versions are how it ought to work with + subjective ratings, which are currenly not used for performance reasons.""" # follows-only: not included models.ReviewRating.objects.create( user=self.remote_user, @@ -48,7 +49,8 @@ class RatingTags(TestCase): book=self.book, privacy="followers", ) - self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 0) + # self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 0) + self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 5) # public: included models.ReviewRating.objects.create( From 9c03bf782e14a991cf317055d4f91eeb44718fc2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 10:15:22 -0700 Subject: [PATCH 006/167] Make an async request to all search connectors This is the untest first pass at re-arranging remote search to work in parallel rather than sequence. It moves a couple functions around (raise_not_valid_url, for example, needs to be in connector_manager.py now to avoid circular imports). It adds a function to Connector objects that generates a search result (either to the isbn endpoint or the free text endpoint) based on the query, which was previously done as part of the search. I also lowered the timeout to 8 seconds by default. --- bookwyrm/connectors/abstract_connector.py | 34 ++++----- bookwyrm/connectors/connector_manager.py | 84 +++++++++++++---------- bookwyrm/settings.py | 2 +- requirements.txt | 1 + 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 56e273886..6685d5a09 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -1,9 +1,8 @@ """ functionality outline for a book data connector """ from abc import ABC, abstractmethod import imghdr -import ipaddress import logging -from urllib.parse import urlparse +import re from django.core.files.base import ContentFile from django.db import transaction @@ -11,7 +10,7 @@ import requests from requests.exceptions import RequestException from bookwyrm import activitypub, models, settings -from .connector_manager import load_more_data, ConnectorException +from .connector_manager import load_more_data, ConnectorException, raise_not_valid_url from .format_mappings import format_mappings @@ -39,6 +38,18 @@ class AbstractMinimalConnector(ABC): for field in self_fields: setattr(self, field, getattr(info, field)) + def get_search_url(self, query): + """ format the query url """ + # Check if the query resembles an ISBN + isbn = re.sub(r"[\W_]", "", query) # removes filler characters + maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13 + if maybe_isbn and self.isbn_search_url and self.isbn_search_url != "": + return f"{self.isbn_search_url}{query}" + + # NOTE: previously, we tried searching isbn and if that produces no results, + # searched as free text. This, instead, only searches isbn if it's isbn-y + return f"{self.search_url}{query}" + def search(self, query, min_confidence=None, timeout=settings.QUERY_TIMEOUT): """free text search""" params = {} @@ -254,9 +265,6 @@ def get_data(url, params=None, timeout=10): # check if the url is blocked raise_not_valid_url(url) - if models.FederatedServer.is_blocked(url): - raise ConnectorException(f"Attempting to load data from blocked url: {url}") - try: resp = requests.get( url, @@ -311,20 +319,6 @@ def get_image(url, timeout=10): return image_content, extension -def raise_not_valid_url(url): - """do some basic reality checks on the url""" - parsed = urlparse(url) - if not parsed.scheme in ["http", "https"]: - raise ConnectorException("Invalid scheme: ", url) - - try: - ipaddress.ip_address(parsed.netloc) - raise ConnectorException("Provided url is an IP address: ", url) - except ValueError: - # it's not an IP address, which is good - pass - - class Mapping: """associate a local database field with a field in an external dataset""" diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 14bb702cb..2b5ab1c9d 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -1,10 +1,11 @@ """ interface with whatever connectors the app has """ -from datetime import datetime +import asyncio import importlib +import ipaddress import logging -import re from urllib.parse import urlparse +import aiohttp from django.dispatch import receiver from django.db.models import signals @@ -21,52 +22,42 @@ class ConnectorException(HTTPError): """when the connector can't do what was asked""" +async def async_connector_search(query, connectors, params): + """Try a number of requests simultaneously""" + timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) + async with aiohttp.ClientSession(timeout=timeout) as session: + for connector in connectors: + url = connector.get_search_url(query) + raise_not_valid_url(url) + + async with session.get(url, params=params) as response: + print("Status:", response.status) + print(response.ok) + print("Content-type:", response.headers['content-type']) + + raw_response = await response.json() + yield { + "connector": connector, + "results": connector.parse_search_data(raw_response) + } + + def search(query, min_confidence=0.1, return_first=False): """find books based on arbitary keywords""" if not query: return [] results = [] - # Have we got a ISBN ? - isbn = re.sub(r"[\W_]", "", query) - maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13 - start_time = datetime.now() - for connector in get_connectors(): - result_set = None - if maybe_isbn and connector.isbn_search_url and connector.isbn_search_url != "": - # Search on ISBN - try: - result_set = connector.isbn_search(isbn) - except Exception as err: # pylint: disable=broad-except - logger.info(err) - # if this fails, we can still try regular search + connectors = list(get_connectors()) - # if no isbn search results, we fallback to generic search - if not result_set: - try: - result_set = connector.search(query, min_confidence=min_confidence) - except Exception as err: # pylint: disable=broad-except - # we don't want *any* error to crash the whole search page - logger.info(err) - continue - - if return_first and result_set: - # if we found anything, return it - return result_set[0] - - if result_set: - results.append( - { - "connector": connector, - "results": result_set, - } - ) - if (datetime.now() - start_time).seconds >= SEARCH_TIMEOUT: - break + # load as many results as we can + params = {"min_confidence": min_confidence} + results = asyncio.run(async_connector_search(query, connectors, params)) if return_first: - return None + # find the best result from all the responses and return that + raise Exception("Not implemented yet") return results @@ -133,3 +124,20 @@ def create_connector(sender, instance, created, *args, **kwargs): """create a connector to an external bookwyrm server""" if instance.application_type == "bookwyrm": get_or_create_connector(f"https://{instance.server_name}") + + +def raise_not_valid_url(url): + """do some basic reality checks on the url""" + parsed = urlparse(url) + if not parsed.scheme in ["http", "https"]: + raise ConnectorException("Invalid scheme: ", url) + + try: + ipaddress.ip_address(parsed.netloc) + raise ConnectorException("Provided url is an IP address: ", url) + except ValueError: + # it's not an IP address, which is good + pass + + if models.FederatedServer.is_blocked(url): + raise ConnectorException(f"Attempting to load data from blocked url: {url}") diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index e16c576e1..dc0d71f30 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -212,7 +212,7 @@ STREAMS = [ # Search configuration # total time in seconds that the instance will spend searching connectors -SEARCH_TIMEOUT = int(env("SEARCH_TIMEOUT", 15)) +SEARCH_TIMEOUT = int(env("SEARCH_TIMEOUT", 8)) # timeout for a query to an individual connector QUERY_TIMEOUT = int(env("QUERY_TIMEOUT", 5)) diff --git a/requirements.txt b/requirements.txt index 7614dc421..c3bdaf757 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +aiohttp==3.8.1 celery==5.2.2 colorthief==0.2.1 Django==3.2.13 From 0adda36da7a2de92ca36805b1b848a8eb100c98e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 10:34:03 -0700 Subject: [PATCH 007/167] Remove search endpoints from Connector Instead of having individual search functions that make individual requests, the connectors will always be searched asynchronously together. The process_seach_response combines the parse and format functions, which could probably be merged into one over-rideable function. The current to-do on this is to remove Inventaire search results that are below the confidence threshhold after search, which used to happen in the `search` function. --- bookwyrm/connectors/abstract_connector.py | 56 +++++++---------------- bookwyrm/connectors/connector_manager.py | 5 +- bookwyrm/connectors/inventaire.py | 8 ---- 3 files changed, 19 insertions(+), 50 deletions(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 6685d5a09..fa3624f82 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -39,52 +39,24 @@ class AbstractMinimalConnector(ABC): setattr(self, field, getattr(info, field)) def get_search_url(self, query): - """ format the query url """ + """format the query url""" # Check if the query resembles an ISBN - isbn = re.sub(r"[\W_]", "", query) # removes filler characters - maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13 - if maybe_isbn and self.isbn_search_url and self.isbn_search_url != "": + if maybe_isbn(query) and self.isbn_search_url and self.isbn_search_url != "": return f"{self.isbn_search_url}{query}" # NOTE: previously, we tried searching isbn and if that produces no results, # searched as free text. This, instead, only searches isbn if it's isbn-y return f"{self.search_url}{query}" - def search(self, query, min_confidence=None, timeout=settings.QUERY_TIMEOUT): - """free text search""" - params = {} - if min_confidence: - params["min_confidence"] = min_confidence - - data = self.get_search_data( - f"{self.search_url}{query}", - params=params, - timeout=timeout, - ) - results = [] - - for doc in self.parse_search_data(data)[:10]: - results.append(self.format_search_result(doc)) - return results - - def isbn_search(self, query, timeout=settings.QUERY_TIMEOUT): - """isbn search""" - params = {} - data = self.get_search_data( - f"{self.isbn_search_url}{query}", - params=params, - timeout=timeout, - ) - results = [] - - # this shouldn't be returning mutliple results, but just in case - for doc in self.parse_isbn_search_data(data)[:10]: - results.append(self.format_isbn_search_result(doc)) - return results - - def get_search_data(self, remote_id, **kwargs): # pylint: disable=no-self-use - """this allows connectors to override the default behavior""" - return get_data(remote_id, **kwargs) + def process_search_response(self, query, data): + """Format the search results based on the formt of the query""" + # TODO: inventaire min confidence + parser = self.parse_search_data + formatter = self.format_search_result + if maybe_isbn(query): + parser = self.parse_isbn_search_data + formatter = self.format_isbn_search_result + return [formatter(doc) for doc in parser(data)[:10]] @abstractmethod def get_or_create_book(self, remote_id): @@ -360,3 +332,9 @@ def unique_physical_format(format_text): # try a direct match, so saving this would be redundant return None return format_text + + +def maybe_isbn(query): + """check if a query looks like an isbn""" + isbn = re.sub(r"[\W_]", "", query) # removes filler characters + return len(isbn) in [10, 13] # ISBN10 or ISBN13 diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 2b5ab1c9d..3c90ba5fe 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -33,12 +33,12 @@ async def async_connector_search(query, connectors, params): async with session.get(url, params=params) as response: print("Status:", response.status) print(response.ok) - print("Content-type:", response.headers['content-type']) + print("Content-type:", response.headers["content-type"]) raw_response = await response.json() yield { "connector": connector, - "results": connector.parse_search_data(raw_response) + "results": connector.process_search_response(query, raw_response), } @@ -48,7 +48,6 @@ def search(query, min_confidence=0.1, return_first=False): return [] results = [] - connectors = list(get_connectors()) # load as many results as we can diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index a9aeb94f9..f25796125 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -77,14 +77,6 @@ class Connector(AbstractConnector): **{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks", "type"]}, } - def search(self, query, min_confidence=None): # pylint: disable=arguments-differ - """overrides default search function with confidence ranking""" - results = super().search(query) - if min_confidence: - # filter the search results after the fact - return [r for r in results if r.confidence >= min_confidence] - return results - def parse_search_data(self, data): return data.get("results") From 9a9cef77665c9c32bf9b7a525564757e678fd549 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 11:16:05 -0700 Subject: [PATCH 008/167] Verify url before async search The database lookup doesn't work during the asyn process, so this change loops through the connectors and grabs the formatted urls before sending it to the async handler. --- bookwyrm/connectors/connector_manager.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 3c90ba5fe..300f1e933 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -22,13 +22,13 @@ class ConnectorException(HTTPError): """when the connector can't do what was asked""" -async def async_connector_search(query, connectors, params): +async def async_connector_search(query, items, params): """Try a number of requests simultaneously""" timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: - for connector in connectors: + for url, connector in items: url = connector.get_search_url(query) - raise_not_valid_url(url) + # raise_not_valid_url(url) async with session.get(url, params=params) as response: print("Status:", response.status) @@ -36,7 +36,7 @@ async def async_connector_search(query, connectors, params): print("Content-type:", response.headers["content-type"]) raw_response = await response.json() - yield { + return { "connector": connector, "results": connector.process_search_response(query, raw_response), } @@ -48,11 +48,18 @@ def search(query, min_confidence=0.1, return_first=False): return [] results = [] - connectors = list(get_connectors()) + items = [] + for connector in get_connectors(): + # get the search url from the connector before sending + url = connector.get_search_url(query) + # check the URL is valid + raise_not_valid_url(url) + items.append((url, connector)) # load as many results as we can params = {"min_confidence": min_confidence} - results = asyncio.run(async_connector_search(query, connectors, params)) + results = asyncio.run(async_connector_search(query, items, params)) + raise Exception("Hi") if return_first: # find the best result from all the responses and return that From 5e81ec75fbf04a6b08d80b83ae90889e96f4e7a9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 11:19:16 -0700 Subject: [PATCH 009/167] Set request headers in async search get request Gotta ask for json --- bookwyrm/connectors/connector_manager.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 300f1e933..a94cdbc59 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -12,7 +12,7 @@ from django.db.models import signals from requests import HTTPError from bookwyrm import book_search, models -from bookwyrm.settings import SEARCH_TIMEOUT +from bookwyrm.settings import SEARCH_TIMEOUT, USER_AGENT from bookwyrm.tasks import app logger = logging.getLogger(__name__) @@ -25,12 +25,19 @@ class ConnectorException(HTTPError): async def async_connector_search(query, items, params): """Try a number of requests simultaneously""" timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) + # pylint: disable=line-too-long + headers = { + "Accept": ( + 'application/json, application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8' + ), + "User-Agent": USER_AGENT, + } async with aiohttp.ClientSession(timeout=timeout) as session: for url, connector in items: url = connector.get_search_url(query) # raise_not_valid_url(url) - async with session.get(url, params=params) as response: + async with session.get(url, headers=headers, params=params) as response: print("Status:", response.status) print(response.ok) print("Content-type:", response.headers["content-type"]) From 45f2199c7120e20d4c098676b0d0b926eadd7e40 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 11:58:39 -0700 Subject: [PATCH 010/167] Gather and wait on async requests This sends out the request tasks all at once and then aggregates the results, instead of just running them one after another asynchronously. --- bookwyrm/connectors/connector_manager.py | 50 +++++++++++++++--------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index a94cdbc59..23cde632b 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -12,7 +12,7 @@ from django.db.models import signals from requests import HTTPError from bookwyrm import book_search, models -from bookwyrm.settings import SEARCH_TIMEOUT, USER_AGENT +from bookwyrm.settings import QUERY_TIMEOUT, USER_AGENT from bookwyrm.tasks import app logger = logging.getLogger(__name__) @@ -22,9 +22,8 @@ class ConnectorException(HTTPError): """when the connector can't do what was asked""" -async def async_connector_search(query, items, params): - """Try a number of requests simultaneously""" - timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) +async def get_results(session, url, params, query, connector): + """try this specific connector""" # pylint: disable=line-too-long headers = { "Accept": ( @@ -32,21 +31,36 @@ async def async_connector_search(query, items, params): ), "User-Agent": USER_AGENT, } + try: + async with session.get(url, headers=headers, params=params) as response: + try: + raw_data = await response.json() + except aiohttp.client_exceptions.ContentTypeError as err: + logger.exception(err) + return None + + return { + "connector": connector, + "results": connector.process_search_response(query, raw_data), + } + except asyncio.TimeoutError: + logger.exception("Connection timout for url: %s", url) + + +async def async_connector_search(query, items, params): + """Try a number of requests simultaneously""" + timeout = aiohttp.ClientTimeout(total=QUERY_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: + tasks = [] for url, connector in items: - url = connector.get_search_url(query) - # raise_not_valid_url(url) + tasks.append( + asyncio.ensure_future( + get_results(session, url, params, query, connector) + ) + ) - async with session.get(url, headers=headers, params=params) as response: - print("Status:", response.status) - print(response.ok) - print("Content-type:", response.headers["content-type"]) - - raw_response = await response.json() - return { - "connector": connector, - "results": connector.process_search_response(query, raw_response), - } + results = await asyncio.gather(*tasks) + return results def search(query, min_confidence=0.1, return_first=False): @@ -66,13 +80,13 @@ def search(query, min_confidence=0.1, return_first=False): # load as many results as we can params = {"min_confidence": min_confidence} results = asyncio.run(async_connector_search(query, items, params)) - raise Exception("Hi") if return_first: # find the best result from all the responses and return that raise Exception("Not implemented yet") - return results + # failed requests will return None, so filter those out + return [r for r in results if r] def first_search_result(query, min_confidence=0.1): From 525e2a591d1329c916355ac0ad549691425d7716 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 12:35:17 -0700 Subject: [PATCH 011/167] More error handing Adds logging and error handling for some of the numerous ways a request could fail (the remote site is down, the url is blocked, etc). I also have the results boxes open by default, which makes it more legible imo. --- bookwyrm/connectors/connector_manager.py | 23 ++++++++++++++++------- bookwyrm/templates/search/book.html | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 23cde632b..69d31a7ea 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -12,7 +12,7 @@ from django.db.models import signals from requests import HTTPError from bookwyrm import book_search, models -from bookwyrm.settings import QUERY_TIMEOUT, USER_AGENT +from bookwyrm.settings import SEARCH_TIMEOUT, USER_AGENT from bookwyrm.tasks import app logger = logging.getLogger(__name__) @@ -33,23 +33,29 @@ async def get_results(session, url, params, query, connector): } try: async with session.get(url, headers=headers, params=params) as response: + if not response.ok: + logger.info("Unable to connect to %s: %s", url, response.reason) + return + try: raw_data = await response.json() except aiohttp.client_exceptions.ContentTypeError as err: logger.exception(err) - return None + return return { "connector": connector, "results": connector.process_search_response(query, raw_data), } except asyncio.TimeoutError: - logger.exception("Connection timout for url: %s", url) + logger.info("Connection timed out for url: %s", url) + except aiohttp.ClientError as err: + logger.exception(err) async def async_connector_search(query, items, params): """Try a number of requests simultaneously""" - timeout = aiohttp.ClientTimeout(total=QUERY_TIMEOUT) + timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: tasks = [] for url, connector in items: @@ -73,8 +79,11 @@ def search(query, min_confidence=0.1, return_first=False): for connector in get_connectors(): # get the search url from the connector before sending url = connector.get_search_url(query) - # check the URL is valid - raise_not_valid_url(url) + try: + raise_not_valid_url(url) + except ConnectorException: + # if this URL is invalid we should skip it and move on + continue items.append((url, connector)) # load as many results as we can @@ -83,7 +92,7 @@ def search(query, min_confidence=0.1, return_first=False): if return_first: # find the best result from all the responses and return that - raise Exception("Not implemented yet") + raise Exception("Not implemented yet") # TODO # failed requests will return None, so filter those out return [r for r in results if r] diff --git a/bookwyrm/templates/search/book.html b/bookwyrm/templates/search/book.html index 7096a55de..d2828eabf 100644 --- a/bookwyrm/templates/search/book.html +++ b/bookwyrm/templates/search/book.html @@ -36,7 +36,7 @@ {% if result_set.results %}
{% if not result_set.connector.local %} -
+
{% endif %} {% if not result_set.connector.local %} From 87fe984462e6a412a09fddaa1508ec7ab1b2c9fa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 12:52:31 -0700 Subject: [PATCH 012/167] Combines search formatter and parser function The parser was extracting the list of search results from the json object returned by the search endpoint, and the formatter was converting an individual json entry into a SearchResult object. This just merged them into one function, because they are never used separately. --- bookwyrm/connectors/abstract_connector.py | 12 +---- bookwyrm/connectors/bookwyrm_connector.py | 14 ++--- bookwyrm/connectors/inventaire.py | 63 ++++++++++------------- bookwyrm/connectors/openlibrary.py | 56 ++++++++++---------- 4 files changed, 60 insertions(+), 85 deletions(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index fa3624f82..6184a225a 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -52,11 +52,9 @@ class AbstractMinimalConnector(ABC): """Format the search results based on the formt of the query""" # TODO: inventaire min confidence parser = self.parse_search_data - formatter = self.format_search_result if maybe_isbn(query): parser = self.parse_isbn_search_data - formatter = self.format_isbn_search_result - return [formatter(doc) for doc in parser(data)[:10]] + return list(parser(data))[:10] @abstractmethod def get_or_create_book(self, remote_id): @@ -66,18 +64,10 @@ class AbstractMinimalConnector(ABC): def parse_search_data(self, data): """turn the result json from a search into a list""" - @abstractmethod - def format_search_result(self, search_result): - """create a SearchResult obj from json""" - @abstractmethod def parse_isbn_search_data(self, data): """turn the result json from a search into a list""" - @abstractmethod - def format_isbn_search_result(self, search_result): - """create a SearchResult obj from json""" - class AbstractConnector(AbstractMinimalConnector): """generic book data connector""" diff --git a/bookwyrm/connectors/bookwyrm_connector.py b/bookwyrm/connectors/bookwyrm_connector.py index 6dcba7c31..ec45c29b6 100644 --- a/bookwyrm/connectors/bookwyrm_connector.py +++ b/bookwyrm/connectors/bookwyrm_connector.py @@ -11,14 +11,10 @@ class Connector(AbstractMinimalConnector): return activitypub.resolve_remote_id(remote_id, model=models.Edition) def parse_search_data(self, data): - return data - - def format_search_result(self, search_result): - search_result["connector"] = self - return SearchResult(**search_result) + for search_result in data: + search_result["connector"] = self + yield SearchResult(**search_result) def parse_isbn_search_data(self, data): - return data - - def format_isbn_search_result(self, search_result): - return self.format_search_result(search_result) + for search_result in data: + yield self.format_search_result(search_result) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index f25796125..7f6191271 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -78,44 +78,37 @@ class Connector(AbstractConnector): } def parse_search_data(self, data): - return data.get("results") - - def format_search_result(self, search_result): - images = search_result.get("image") - cover = f"{self.covers_url}/img/entities/{images[0]}" if images else None - # a deeply messy translation of inventaire's scores - confidence = float(search_result.get("_score", 0.1)) - confidence = 0.1 if confidence < 150 else 0.999 - return SearchResult( - title=search_result.get("label"), - key=self.get_remote_id(search_result.get("uri")), - author=search_result.get("description"), - view_link=f"{self.base_url}/entity/{search_result.get('uri')}", - cover=cover, - confidence=confidence, - connector=self, - ) + for search_result in data.get("results"): + images = search_result.get("image") + cover = f"{self.covers_url}/img/entities/{images[0]}" if images else None + # a deeply messy translation of inventaire's scores + confidence = float(search_result.get("_score", 0.1)) + confidence = 0.1 if confidence < 150 else 0.999 + yield SearchResult( + title=search_result.get("label"), + key=self.get_remote_id(search_result.get("uri")), + author=search_result.get("description"), + view_link=f"{self.base_url}/entity/{search_result.get('uri')}", + cover=cover, + confidence=confidence, + connector=self, + ) def parse_isbn_search_data(self, data): """got some daaaata""" - results = data.get("entities") - if not results: - return [] - return list(results.values()) - - def format_isbn_search_result(self, search_result): - """totally different format than a regular search result""" - title = search_result.get("claims", {}).get("wdt:P1476", []) - if not title: - return None - return SearchResult( - title=title[0], - key=self.get_remote_id(search_result.get("uri")), - author=search_result.get("description"), - view_link=f"{self.base_url}/entity/{search_result.get('uri')}", - cover=self.get_cover_url(search_result.get("image")), - connector=self, - ) + results = data.get("entities", []) + for search_result in list(results.values()): + title = search_result.get("claims", {}).get("wdt:P1476", []) + if not title: + continue + yield SearchResult( + title=title[0], + key=self.get_remote_id(search_result.get("uri")), + author=search_result.get("description"), + view_link=f"{self.base_url}/entity/{search_result.get('uri')}", + cover=self.get_cover_url(search_result.get("image")), + connector=self, + ) def is_work_data(self, data): return data.get("type") == "work" diff --git a/bookwyrm/connectors/openlibrary.py b/bookwyrm/connectors/openlibrary.py index 118222a16..fa9aeeb30 100644 --- a/bookwyrm/connectors/openlibrary.py +++ b/bookwyrm/connectors/openlibrary.py @@ -153,38 +153,34 @@ class Connector(AbstractConnector): return f"{self.covers_url}/b/id/{image_name}" def parse_search_data(self, data): - return data.get("docs") - - def format_search_result(self, search_result): - # build the remote id from the openlibrary key - key = self.books_url + search_result["key"] - author = search_result.get("author_name") or ["Unknown"] - cover_blob = search_result.get("cover_i") - cover = self.get_cover_url([cover_blob], size="M") if cover_blob else None - return SearchResult( - title=search_result.get("title"), - key=key, - author=", ".join(author), - connector=self, - year=search_result.get("first_publish_year"), - cover=cover, - ) + for search_result in data.get("docs"): + # build the remote id from the openlibrary key + key = self.books_url + search_result["key"] + author = search_result.get("author_name") or ["Unknown"] + cover_blob = search_result.get("cover_i") + cover = self.get_cover_url([cover_blob], size="M") if cover_blob else None + yield SearchResult( + title=search_result.get("title"), + key=key, + author=", ".join(author), + connector=self, + year=search_result.get("first_publish_year"), + cover=cover, + ) def parse_isbn_search_data(self, data): - return list(data.values()) - - def format_isbn_search_result(self, search_result): - # build the remote id from the openlibrary key - key = self.books_url + search_result["key"] - authors = search_result.get("authors") or [{"name": "Unknown"}] - author_names = [author.get("name") for author in authors] - return SearchResult( - title=search_result.get("title"), - key=key, - author=", ".join(author_names), - connector=self, - year=search_result.get("publish_date"), - ) + for search_result in list(data.values()): + # build the remote id from the openlibrary key + key = self.books_url + search_result["key"] + authors = search_result.get("authors") or [{"name": "Unknown"}] + author_names = [author.get("name") for author in authors] + yield SearchResult( + title=search_result.get("title"), + key=key, + author=", ".join(author_names), + connector=self, + year=search_result.get("publish_date"), + ) def load_edition_data(self, olkey): """query openlibrary for editions of a work""" From af19d728d2264592463b6211411d0850c5ad7b40 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 16:16:10 -0700 Subject: [PATCH 013/167] Removes outdated unit tests --- bookwyrm/connectors/bookwyrm_connector.py | 3 +- bookwyrm/connectors/inventaire.py | 6 ++- .../connectors/test_abstract_connector.py | 6 --- .../test_abstract_minimal_connector.py | 46 ----------------- .../connectors/test_bookwyrm_connector.py | 12 ++--- .../connectors/test_connector_manager.py | 28 ----------- .../connectors/test_inventaire_connector.py | 50 +++---------------- bookwyrm/tests/test_book_search.py | 6 --- 8 files changed, 16 insertions(+), 141 deletions(-) diff --git a/bookwyrm/connectors/bookwyrm_connector.py b/bookwyrm/connectors/bookwyrm_connector.py index ec45c29b6..05612d9eb 100644 --- a/bookwyrm/connectors/bookwyrm_connector.py +++ b/bookwyrm/connectors/bookwyrm_connector.py @@ -17,4 +17,5 @@ class Connector(AbstractMinimalConnector): def parse_isbn_search_data(self, data): for search_result in data: - yield self.format_search_result(search_result) + search_result["connector"] = self + yield SearchResult(**search_result) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index 7f6191271..0495d8c2f 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -78,7 +78,7 @@ class Connector(AbstractConnector): } def parse_search_data(self, data): - for search_result in data.get("results"): + for search_result in data.get("results", []): images = search_result.get("image") cover = f"{self.covers_url}/img/entities/{images[0]}" if images else None # a deeply messy translation of inventaire's scores @@ -96,7 +96,9 @@ class Connector(AbstractConnector): def parse_isbn_search_data(self, data): """got some daaaata""" - results = data.get("entities", []) + results = data.get("entities") + if not results: + return for search_result in list(results.values()): title = search_result.get("claims", {}).get("wdt:P1476", []) if not title: diff --git a/bookwyrm/tests/connectors/test_abstract_connector.py b/bookwyrm/tests/connectors/test_abstract_connector.py index 26742c05e..eb3a7b01a 100644 --- a/bookwyrm/tests/connectors/test_abstract_connector.py +++ b/bookwyrm/tests/connectors/test_abstract_connector.py @@ -42,15 +42,9 @@ class AbstractConnector(TestCase): generated_remote_link_field = "openlibrary_link" - def format_search_result(self, search_result): - return search_result - def parse_search_data(self, data): return data - def format_isbn_search_result(self, search_result): - return search_result - def parse_isbn_search_data(self, data): return data diff --git a/bookwyrm/tests/connectors/test_abstract_minimal_connector.py b/bookwyrm/tests/connectors/test_abstract_minimal_connector.py index a90ce0c7e..06da8741c 100644 --- a/bookwyrm/tests/connectors/test_abstract_minimal_connector.py +++ b/bookwyrm/tests/connectors/test_abstract_minimal_connector.py @@ -1,6 +1,5 @@ """ testing book data connectors """ from django.test import TestCase -import responses from bookwyrm import models from bookwyrm.connectors import abstract_connector @@ -25,18 +24,12 @@ class AbstractConnector(TestCase): class TestConnector(abstract_connector.AbstractMinimalConnector): """nothing added here""" - def format_search_result(self, search_result): - return search_result - def get_or_create_book(self, remote_id): pass def parse_search_data(self, data): return data - def format_isbn_search_result(self, search_result): - return search_result - def parse_isbn_search_data(self, data): return data @@ -54,45 +47,6 @@ class AbstractConnector(TestCase): self.assertIsNone(connector.name) self.assertEqual(connector.identifier, "example.com") - @responses.activate - def test_search(self): - """makes an http request to the outside service""" - responses.add( - responses.GET, - "https://example.com/search?q=a%20book%20title", - json=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"], - status=200, - ) - results = self.test_connector.search("a book title") - self.assertEqual(len(results), 10) - self.assertEqual(results[0], "a") - self.assertEqual(results[1], "b") - self.assertEqual(results[2], "c") - - @responses.activate - def test_search_min_confidence(self): - """makes an http request to the outside service""" - responses.add( - responses.GET, - "https://example.com/search?q=a%20book%20title&min_confidence=1", - json=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"], - status=200, - ) - results = self.test_connector.search("a book title", min_confidence=1) - self.assertEqual(len(results), 10) - - @responses.activate - def test_isbn_search(self): - """makes an http request to the outside service""" - responses.add( - responses.GET, - "https://example.com/isbn?q=123456", - json=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"], - status=200, - ) - results = self.test_connector.isbn_search("123456") - self.assertEqual(len(results), 10) - def test_create_mapping(self): """maps remote fields for book data to bookwyrm activitypub fields""" mapping = Mapping("isbn") diff --git a/bookwyrm/tests/connectors/test_bookwyrm_connector.py b/bookwyrm/tests/connectors/test_bookwyrm_connector.py index 585080e66..b9642a50e 100644 --- a/bookwyrm/tests/connectors/test_bookwyrm_connector.py +++ b/bookwyrm/tests/connectors/test_bookwyrm_connector.py @@ -30,14 +30,11 @@ class BookWyrmConnector(TestCase): result = self.connector.get_or_create_book(book.remote_id) self.assertEqual(book, result) - def test_format_search_result(self): + def test_parse_search_data(self): """create a SearchResult object from search response json""" datafile = pathlib.Path(__file__).parent.joinpath("../data/bw_search.json") search_data = json.loads(datafile.read_bytes()) - results = self.connector.parse_search_data(search_data) - self.assertIsInstance(results, list) - - result = self.connector.format_search_result(results[0]) + result = list(self.connector.parse_search_data(search_data))[0] self.assertIsInstance(result, SearchResult) self.assertEqual(result.title, "Jonathan Strange and Mr Norrell") self.assertEqual(result.key, "https://example.com/book/122") @@ -45,10 +42,9 @@ class BookWyrmConnector(TestCase): self.assertEqual(result.year, 2017) self.assertEqual(result.connector, self.connector) - def test_format_isbn_search_result(self): + def test_parse_isbn_search_data(self): """just gotta attach the connector""" datafile = pathlib.Path(__file__).parent.joinpath("../data/bw_search.json") search_data = json.loads(datafile.read_bytes()) - results = self.connector.parse_isbn_search_data(search_data) - result = self.connector.format_isbn_search_result(results[0]) + result = list(self.connector.parse_isbn_search_data(search_data))[0] self.assertEqual(result.connector, self.connector) diff --git a/bookwyrm/tests/connectors/test_connector_manager.py b/bookwyrm/tests/connectors/test_connector_manager.py index c88a8036a..c0c09147e 100644 --- a/bookwyrm/tests/connectors/test_connector_manager.py +++ b/bookwyrm/tests/connectors/test_connector_manager.py @@ -49,39 +49,11 @@ class ConnectorManager(TestCase): self.assertEqual(len(connectors), 1) self.assertIsInstance(connectors[0], BookWyrmConnector) - @responses.activate - def test_search_plaintext(self): - """search all connectors""" - responses.add( - responses.GET, - "http://fake.ciom/search/Example?min_confidence=0.1", - json=[{"title": "Hello", "key": "https://www.example.com/search/1"}], - ) - results = connector_manager.search("Example") - self.assertEqual(len(results), 1) - self.assertEqual(len(results[0]["results"]), 1) - self.assertEqual(results[0]["connector"].identifier, "test_connector_remote") - self.assertEqual(results[0]["results"][0].title, "Hello") - def test_search_empty_query(self): """don't panic on empty queries""" results = connector_manager.search("") self.assertEqual(results, []) - @responses.activate - def test_search_isbn(self): - """special handling if a query resembles an isbn""" - responses.add( - responses.GET, - "http://fake.ciom/isbn/0000000000", - json=[{"title": "Hello", "key": "https://www.example.com/search/1"}], - ) - results = connector_manager.search("0000000000") - self.assertEqual(len(results), 1) - self.assertEqual(len(results[0]["results"]), 1) - self.assertEqual(results[0]["connector"].identifier, "test_connector_remote") - self.assertEqual(results[0]["results"][0].title, "Hello") - def test_first_search_result(self): """only get one search result""" result = connector_manager.first_search_result("Example") diff --git a/bookwyrm/tests/connectors/test_inventaire_connector.py b/bookwyrm/tests/connectors/test_inventaire_connector.py index 55727a600..7b526f224 100644 --- a/bookwyrm/tests/connectors/test_inventaire_connector.py +++ b/bookwyrm/tests/connectors/test_inventaire_connector.py @@ -66,38 +66,14 @@ class Inventaire(TestCase): with self.assertRaises(ConnectorException): self.connector.get_book_data("https://test.url/ok") - @responses.activate - def test_search(self): - """min confidence filtering""" - responses.add( - responses.GET, - "https://inventaire.io/search?q=hi", - json={ - "results": [ - { - "_score": 200, - "label": "hello", - }, - { - "_score": 100, - "label": "hi", - }, - ], - }, - ) - results = self.connector.search("hi", min_confidence=0.5) - self.assertEqual(len(results), 1) - self.assertEqual(results[0].title, "hello") - - def test_format_search_result(self): + def test_parse_search_data(self): """json to search result objs""" search_file = pathlib.Path(__file__).parent.joinpath( "../data/inventaire_search.json" ) search_results = json.loads(search_file.read_bytes()) - results = self.connector.parse_search_data(search_results) - formatted = self.connector.format_search_result(results[0]) + formatted = list(self.connector.parse_search_data(search_results))[0] self.assertEqual(formatted.title, "The Stories of Vladimir Nabokov") self.assertEqual( @@ -178,15 +154,14 @@ class Inventaire(TestCase): result = self.connector.resolve_keys(keys) self.assertEqual(result, ["epistolary novel", "crime novel"]) - def test_isbn_search(self): + def test_pase_isbn_search_data(self): """another search type""" search_file = pathlib.Path(__file__).parent.joinpath( "../data/inventaire_isbn_search.json" ) search_results = json.loads(search_file.read_bytes()) - results = self.connector.parse_isbn_search_data(search_results) - formatted = self.connector.format_isbn_search_result(results[0]) + formatted = list(self.connector.parse_isbn_search_data(search_results))[0] self.assertEqual(formatted.title, "L'homme aux cercles bleus") self.assertEqual( @@ -198,25 +173,12 @@ class Inventaire(TestCase): "https://covers.inventaire.io/img/entities/12345", ) - def test_isbn_search_empty(self): + def test_parse_isbn_search_data_empty(self): """another search type""" search_results = {} - results = self.connector.parse_isbn_search_data(search_results) + results = list(self.connector.parse_isbn_search_data(search_results)) self.assertEqual(results, []) - def test_isbn_search_no_title(self): - """another search type""" - search_file = pathlib.Path(__file__).parent.joinpath( - "../data/inventaire_isbn_search.json" - ) - search_results = json.loads(search_file.read_bytes()) - search_results["entities"]["isbn:9782290349229"]["claims"]["wdt:P1476"] = None - - result = self.connector.format_isbn_search_result( - search_results.get("entities") - ) - self.assertIsNone(result) - def test_is_work_data(self): """is it a work""" work_file = pathlib.Path(__file__).parent.joinpath( diff --git a/bookwyrm/tests/test_book_search.py b/bookwyrm/tests/test_book_search.py index 16435ffff..141e3906b 100644 --- a/bookwyrm/tests/test_book_search.py +++ b/bookwyrm/tests/test_book_search.py @@ -102,18 +102,12 @@ class BookSearch(TestCase): class TestConnector(AbstractMinimalConnector): """nothing added here""" - def format_search_result(self, search_result): - return search_result - def get_or_create_book(self, remote_id): pass def parse_search_data(self, data): return data - def format_isbn_search_result(self, search_result): - return search_result - def parse_isbn_search_data(self, data): return data From 83ee5a756f48622243b5e0d0347092ca0564ebfa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 16:42:37 -0700 Subject: [PATCH 014/167] Filter intentaire results by confidence --- bookwyrm/connectors/abstract_connector.py | 10 ++++------ bookwyrm/connectors/bookwyrm_connector.py | 2 +- bookwyrm/connectors/connector_manager.py | 12 ++++++------ bookwyrm/connectors/inventaire.py | 4 +++- bookwyrm/connectors/openlibrary.py | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 6184a225a..dc4be4b3d 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -48,20 +48,18 @@ class AbstractMinimalConnector(ABC): # searched as free text. This, instead, only searches isbn if it's isbn-y return f"{self.search_url}{query}" - def process_search_response(self, query, data): + def process_search_response(self, query, data, min_confidence): """Format the search results based on the formt of the query""" - # TODO: inventaire min confidence - parser = self.parse_search_data if maybe_isbn(query): - parser = self.parse_isbn_search_data - return list(parser(data))[:10] + return list(self.parse_isbn_search_data(data))[:10] + return list(self.parse_search_data(data, min_confidence))[:10] @abstractmethod def get_or_create_book(self, remote_id): """pull up a book record by whatever means possible""" @abstractmethod - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): """turn the result json from a search into a list""" @abstractmethod diff --git a/bookwyrm/connectors/bookwyrm_connector.py b/bookwyrm/connectors/bookwyrm_connector.py index 05612d9eb..e07a0b281 100644 --- a/bookwyrm/connectors/bookwyrm_connector.py +++ b/bookwyrm/connectors/bookwyrm_connector.py @@ -10,7 +10,7 @@ class Connector(AbstractMinimalConnector): def get_or_create_book(self, remote_id): return activitypub.resolve_remote_id(remote_id, model=models.Edition) - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): for search_result in data: search_result["connector"] = self yield SearchResult(**search_result) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 69d31a7ea..0488421e9 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -22,7 +22,7 @@ class ConnectorException(HTTPError): """when the connector can't do what was asked""" -async def get_results(session, url, params, query, connector): +async def get_results(session, url, min_confidence, query, connector): """try this specific connector""" # pylint: disable=line-too-long headers = { @@ -31,6 +31,7 @@ async def get_results(session, url, params, query, connector): ), "User-Agent": USER_AGENT, } + params = {"min_confidence": min_confidence} try: async with session.get(url, headers=headers, params=params) as response: if not response.ok: @@ -45,7 +46,7 @@ async def get_results(session, url, params, query, connector): return { "connector": connector, - "results": connector.process_search_response(query, raw_data), + "results": connector.process_search_response(query, raw_data, min_confidence), } except asyncio.TimeoutError: logger.info("Connection timed out for url: %s", url) @@ -53,7 +54,7 @@ async def get_results(session, url, params, query, connector): logger.exception(err) -async def async_connector_search(query, items, params): +async def async_connector_search(query, items, min_confidence): """Try a number of requests simultaneously""" timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: @@ -61,7 +62,7 @@ async def async_connector_search(query, items, params): for url, connector in items: tasks.append( asyncio.ensure_future( - get_results(session, url, params, query, connector) + get_results(session, url, min_confidence, query, connector) ) ) @@ -87,8 +88,7 @@ def search(query, min_confidence=0.1, return_first=False): items.append((url, connector)) # load as many results as we can - params = {"min_confidence": min_confidence} - results = asyncio.run(async_connector_search(query, items, params)) + results = asyncio.run(async_connector_search(query, items, min_confidence)) if return_first: # find the best result from all the responses and return that diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index 0495d8c2f..c13f4e3e6 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -77,13 +77,15 @@ class Connector(AbstractConnector): **{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks", "type"]}, } - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): for search_result in data.get("results", []): images = search_result.get("image") cover = f"{self.covers_url}/img/entities/{images[0]}" if images else None # a deeply messy translation of inventaire's scores confidence = float(search_result.get("_score", 0.1)) confidence = 0.1 if confidence < 150 else 0.999 + if confidence < min_confidence: + continue yield SearchResult( title=search_result.get("label"), key=self.get_remote_id(search_result.get("uri")), diff --git a/bookwyrm/connectors/openlibrary.py b/bookwyrm/connectors/openlibrary.py index fa9aeeb30..2b625dffc 100644 --- a/bookwyrm/connectors/openlibrary.py +++ b/bookwyrm/connectors/openlibrary.py @@ -152,7 +152,7 @@ class Connector(AbstractConnector): image_name = f"{cover_id}-{size}.jpg" return f"{self.covers_url}/b/id/{image_name}" - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): for search_result in data.get("docs"): # build the remote id from the openlibrary key key = self.books_url + search_result["key"] From 98ed03b6b45701d526b48add7931121683723169 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 30 May 2022 17:00:34 -0700 Subject: [PATCH 015/167] Python formatting and test update --- bookwyrm/connectors/connector_manager.py | 4 +++- .../connectors/test_bookwyrm_connector.py | 2 +- .../connectors/test_inventaire_connector.py | 2 +- .../connectors/test_openlibrary_connector.py | 24 +++---------------- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 0488421e9..fc7849249 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -46,7 +46,9 @@ async def get_results(session, url, min_confidence, query, connector): return { "connector": connector, - "results": connector.process_search_response(query, raw_data, min_confidence), + "results": connector.process_search_response( + query, raw_data, min_confidence + ), } except asyncio.TimeoutError: logger.info("Connection timed out for url: %s", url) diff --git a/bookwyrm/tests/connectors/test_bookwyrm_connector.py b/bookwyrm/tests/connectors/test_bookwyrm_connector.py index b9642a50e..1e369ca01 100644 --- a/bookwyrm/tests/connectors/test_bookwyrm_connector.py +++ b/bookwyrm/tests/connectors/test_bookwyrm_connector.py @@ -34,7 +34,7 @@ class BookWyrmConnector(TestCase): """create a SearchResult object from search response json""" datafile = pathlib.Path(__file__).parent.joinpath("../data/bw_search.json") search_data = json.loads(datafile.read_bytes()) - result = list(self.connector.parse_search_data(search_data))[0] + result = list(self.connector.parse_search_data(search_data, 0))[0] self.assertIsInstance(result, SearchResult) self.assertEqual(result.title, "Jonathan Strange and Mr Norrell") self.assertEqual(result.key, "https://example.com/book/122") diff --git a/bookwyrm/tests/connectors/test_inventaire_connector.py b/bookwyrm/tests/connectors/test_inventaire_connector.py index 7b526f224..3bba9ece3 100644 --- a/bookwyrm/tests/connectors/test_inventaire_connector.py +++ b/bookwyrm/tests/connectors/test_inventaire_connector.py @@ -73,7 +73,7 @@ class Inventaire(TestCase): ) search_results = json.loads(search_file.read_bytes()) - formatted = list(self.connector.parse_search_data(search_results))[0] + formatted = list(self.connector.parse_search_data(search_results, 0))[0] self.assertEqual(formatted.title, "The Stories of Vladimir Nabokov") self.assertEqual( diff --git a/bookwyrm/tests/connectors/test_openlibrary_connector.py b/bookwyrm/tests/connectors/test_openlibrary_connector.py index c05eb1a94..69e4f847c 100644 --- a/bookwyrm/tests/connectors/test_openlibrary_connector.py +++ b/bookwyrm/tests/connectors/test_openlibrary_connector.py @@ -122,21 +122,11 @@ class Openlibrary(TestCase): self.assertEqual(result, "https://covers.openlibrary.org/b/id/image-L.jpg") def test_parse_search_result(self): - """extract the results from the search json response""" - datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_search.json") - search_data = json.loads(datafile.read_bytes()) - result = self.connector.parse_search_data(search_data) - self.assertIsInstance(result, list) - self.assertEqual(len(result), 2) - - def test_format_search_result(self): """translate json from openlibrary into SearchResult""" datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_search.json") search_data = json.loads(datafile.read_bytes()) - results = self.connector.parse_search_data(search_data) - self.assertIsInstance(results, list) + result = list(self.connector.parse_search_data(search_data, 0))[0] - result = self.connector.format_search_result(results[0]) self.assertIsInstance(result, SearchResult) self.assertEqual(result.title, "This Is How You Lose the Time War") self.assertEqual(result.key, "https://openlibrary.org/works/OL20639540W") @@ -148,18 +138,10 @@ class Openlibrary(TestCase): """extract the results from the search json response""" datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_isbn_search.json") search_data = json.loads(datafile.read_bytes()) - result = self.connector.parse_isbn_search_data(search_data) - self.assertIsInstance(result, list) + result = list(self.connector.parse_isbn_search_data(search_data)) self.assertEqual(len(result), 1) - def test_format_isbn_search_result(self): - """translate json from openlibrary into SearchResult""" - datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_isbn_search.json") - search_data = json.loads(datafile.read_bytes()) - results = self.connector.parse_isbn_search_data(search_data) - self.assertIsInstance(results, list) - - result = self.connector.format_isbn_search_result(results[0]) + result = result[0] self.assertIsInstance(result, SearchResult) self.assertEqual(result.title, "Les ombres errantes") self.assertEqual(result.key, "https://openlibrary.org/books/OL16262504M") From a053f209619429706f33baeeb2844a48756acce3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 08:20:59 -0700 Subject: [PATCH 016/167] Re-implements return first option Since we get all the results quickly now, this aggregates all the results that came back and sorts them by confidence, and returns the highest confidence result. The confidences aren't great on free text search, but conceptually that's how it should work at least. It may make sense to aggregate the search results in all contexts, but I'll propose that in a separate PR. --- bookwyrm/book_search.py | 4 ++-- bookwyrm/connectors/connector_manager.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bookwyrm/book_search.py b/bookwyrm/book_search.py index e42a6d8c3..4b0a6eab9 100644 --- a/bookwyrm/book_search.py +++ b/bookwyrm/book_search.py @@ -148,8 +148,8 @@ class SearchResult: def __repr__(self): # pylint: disable=consider-using-f-string - return "".format( - self.key, self.title, self.author + return "".format( + self.key, self.title, self.author, self.confidence ) def json(self): diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index fc7849249..5c8b43fdb 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -91,13 +91,16 @@ def search(query, min_confidence=0.1, return_first=False): # load as many results as we can results = asyncio.run(async_connector_search(query, items, min_confidence)) + results = [r for r in results if r] if return_first: # find the best result from all the responses and return that - raise Exception("Not implemented yet") # TODO + all_results = [r for con in results for r in con["results"]] + all_results = sorted(all_results, key=lambda r: r.confidence, reverse=True) + return all_results[0] # failed requests will return None, so filter those out - return [r for r in results if r] + return results def first_search_result(query, min_confidence=0.1): From 5e99002aad76fd8dcadf8b5b3f6ef9c4bcac262b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 08:25:02 -0700 Subject: [PATCH 017/167] Raise priority for external connectors in initdb By default, OpenLibrary and Inventaire were prioritzed below other BookWyrm nodes. In practice, people have gotten better search results from these connectors, hence the change. With the search refactor, this has much less impact, but it will show these search results higher in the list. If the results page shows all the connectors' results integrated, this field should be removed entirely. --- bookwyrm/management/commands/initdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/management/commands/initdb.py b/bookwyrm/management/commands/initdb.py index 160502ca0..23020a0a6 100644 --- a/bookwyrm/management/commands/initdb.py +++ b/bookwyrm/management/commands/initdb.py @@ -89,7 +89,7 @@ def init_connectors(): covers_url="https://inventaire.io", search_url="https://inventaire.io/api/search?types=works&types=works&search=", isbn_search_url="https://inventaire.io/api/entities?action=by-uris&uris=isbn%3A", - priority=3, + priority=1, ) models.Connector.objects.create( @@ -101,7 +101,7 @@ def init_connectors(): covers_url="https://covers.openlibrary.org", search_url="https://openlibrary.org/search?q=", isbn_search_url="https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:", - priority=3, + priority=1, ) From 05fd30cfcf50338b694e9c8c1e07d2c30ade3317 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 08:37:07 -0700 Subject: [PATCH 018/167] Pylint fixes in connector tests --- bookwyrm/tests/connectors/test_abstract_connector.py | 2 +- bookwyrm/tests/connectors/test_abstract_minimal_connector.py | 2 +- bookwyrm/tests/test_book_search.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/connectors/test_abstract_connector.py b/bookwyrm/tests/connectors/test_abstract_connector.py index eb3a7b01a..02ac5c66a 100644 --- a/bookwyrm/tests/connectors/test_abstract_connector.py +++ b/bookwyrm/tests/connectors/test_abstract_connector.py @@ -42,7 +42,7 @@ class AbstractConnector(TestCase): generated_remote_link_field = "openlibrary_link" - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): return data def parse_isbn_search_data(self, data): diff --git a/bookwyrm/tests/connectors/test_abstract_minimal_connector.py b/bookwyrm/tests/connectors/test_abstract_minimal_connector.py index 06da8741c..119ca3581 100644 --- a/bookwyrm/tests/connectors/test_abstract_minimal_connector.py +++ b/bookwyrm/tests/connectors/test_abstract_minimal_connector.py @@ -27,7 +27,7 @@ class AbstractConnector(TestCase): def get_or_create_book(self, remote_id): pass - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): return data def parse_isbn_search_data(self, data): diff --git a/bookwyrm/tests/test_book_search.py b/bookwyrm/tests/test_book_search.py index 141e3906b..7274cb49c 100644 --- a/bookwyrm/tests/test_book_search.py +++ b/bookwyrm/tests/test_book_search.py @@ -105,7 +105,7 @@ class BookSearch(TestCase): def get_or_create_book(self, remote_id): pass - def parse_search_data(self, data): + def parse_search_data(self, data, min_confidence): return data def parse_isbn_search_data(self, data): From 969db13ff2c43421357509bbe3d5a562983ba06f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 08:49:23 -0700 Subject: [PATCH 019/167] Safely return None in remote search return_first --- bookwyrm/connectors/connector_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 5c8b43fdb..af79b2483 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -97,7 +97,7 @@ def search(query, min_confidence=0.1, return_first=False): # find the best result from all the responses and return that all_results = [r for con in results for r in con["results"]] all_results = sorted(all_results, key=lambda r: r.confidence, reverse=True) - return all_results[0] + return all_results[0] if all_results else None # failed requests will return None, so filter those out return results From c3b35760a285faecc82a465835fc33e0fb006913 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 09:32:32 -0700 Subject: [PATCH 020/167] Updates test mocks for remote search --- bookwyrm/connectors/connector_manager.py | 1 + bookwyrm/tests/views/test_search.py | 30 ++++++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index af79b2483..86774af56 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -86,6 +86,7 @@ def search(query, min_confidence=0.1, return_first=False): raise_not_valid_url(url) except ConnectorException: # if this URL is invalid we should skip it and move on + logger.info("Request denied to blocked domain: %s", url) continue items.append((url, connector)) diff --git a/bookwyrm/tests/views/test_search.py b/bookwyrm/tests/views/test_search.py index 2df04f588..51166f2fa 100644 --- a/bookwyrm/tests/views/test_search.py +++ b/bookwyrm/tests/views/test_search.py @@ -1,6 +1,5 @@ """ test for app action functionality """ import json -import pathlib from unittest.mock import patch from django.contrib.auth.models import AnonymousUser @@ -8,9 +7,9 @@ from django.http import JsonResponse from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory -import responses from bookwyrm import models, views +from bookwyrm.book_search import SearchResult from bookwyrm.settings import DOMAIN from bookwyrm.tests.validate_html import validate_html @@ -65,12 +64,11 @@ class Views(TestCase): self.assertIsInstance(response, TemplateResponse) validate_html(response.render()) - @responses.activate def test_search_books(self): """searches remote connectors""" view = views.Search.as_view() - models.Connector.objects.create( + connector = models.Connector.objects.create( identifier="example.com", connector_file="openlibrary", base_url="https://example.com", @@ -78,26 +76,24 @@ class Views(TestCase): covers_url="https://example.com/covers", search_url="https://example.com/search?q=", ) - datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_search.json") - search_data = json.loads(datafile.read_bytes()) - responses.add( - responses.GET, "https://example.com/search?q=Test%20Book", json=search_data - ) + mock_result = SearchResult(title="Mock Book", connector=connector, key="hello") request = self.factory.get("", {"q": "Test Book", "remote": True}) request.user = self.local_user with patch("bookwyrm.views.search.is_api_request") as is_api: is_api.return_value = False - response = view(request) + with patch("bookwyrm.connectors.connector_manager.search") as remote_search: + remote_search.return_value = [ + {"results": [mock_result], "connector": connector} + ] + response = view(request) + self.assertIsInstance(response, TemplateResponse) validate_html(response.render()) connector_results = response.context_data["results"] self.assertEqual(len(connector_results), 2) self.assertEqual(connector_results[0]["results"][0].title, "Test Book") - self.assertEqual( - connector_results[1]["results"][0].title, - "This Is How You Lose the Time War", - ) + self.assertEqual(connector_results[1]["results"][0].title, "Mock Book") # don't search remote request = self.factory.get("", {"q": "Test Book", "remote": True}) @@ -106,7 +102,11 @@ class Views(TestCase): request.user = anonymous_user with patch("bookwyrm.views.search.is_api_request") as is_api: is_api.return_value = False - response = view(request) + with patch("bookwyrm.connectors.connector_manager.search") as remote_search: + remote_search.return_value = [ + {"results": [mock_result], "connector": connector} + ] + response = view(request) self.assertIsInstance(response, TemplateResponse) validate_html(response.render()) connector_results = response.context_data["results"] From 374fdcf467a7dd386633b69ed4ad2b409df42b4b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 10:22:49 -0700 Subject: [PATCH 021/167] Use relative list order ranking in openlibrary search Set OpenLibrary search condifidence based on the provided result order, just using 1/(list index), so the first has rank 1, the second 0.5, the third 0.33, et cetera. --- bookwyrm/connectors/openlibrary.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bookwyrm/connectors/openlibrary.py b/bookwyrm/connectors/openlibrary.py index 2b625dffc..c1527527e 100644 --- a/bookwyrm/connectors/openlibrary.py +++ b/bookwyrm/connectors/openlibrary.py @@ -153,12 +153,17 @@ class Connector(AbstractConnector): return f"{self.covers_url}/b/id/{image_name}" def parse_search_data(self, data, min_confidence): - for search_result in data.get("docs"): + for idx, search_result in enumerate(data.get("docs")): # build the remote id from the openlibrary key key = self.books_url + search_result["key"] author = search_result.get("author_name") or ["Unknown"] cover_blob = search_result.get("cover_i") cover = self.get_cover_url([cover_blob], size="M") if cover_blob else None + + # OL doesn't provide confidence, but it does sort by an internal ranking, so + # this confidence value is relative to the list position + confidence = 1 / (idx + 1) + yield SearchResult( title=search_result.get("title"), key=key, @@ -166,6 +171,7 @@ class Connector(AbstractConnector): connector=self, year=search_result.get("first_publish_year"), cover=cover, + confidence=confidence, ) def parse_isbn_search_data(self, data): From 20f452ebf4563e6b29ea7a2aec82ef65a246584c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 12:23:59 -0700 Subject: [PATCH 022/167] Clip column in about page Text in the superlatives section can cause this column to expand outside the container. --- bookwyrm/templates/about/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/about/layout.html b/bookwyrm/templates/about/layout.html index 458e4b1d1..e921fcd29 100644 --- a/bookwyrm/templates/about/layout.html +++ b/bookwyrm/templates/about/layout.html @@ -50,7 +50,7 @@ -
+
{% block about_content %}{% endblock %}
From d149e57494757143ed905802e5a0d24930d22d2f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 12:41:57 -0700 Subject: [PATCH 023/167] Split expand book data task into per-edition tasks Loading every edition in one task takes ages, and produces a large task that clogs up the queue. This will create more, smaller tasks that will finish more quickly. --- bookwyrm/connectors/connector_manager.py | 9 +++++++++ bookwyrm/connectors/inventaire.py | 18 +++++++++++------- bookwyrm/connectors/openlibrary.py | 4 ++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 86774af56..37b093aa9 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -152,6 +152,15 @@ def load_more_data(connector_id, book_id): connector.expand_book_data(book) +@app.task(queue="low_priority") +def create_edition_task(connector_id, work_id, data): + """separate task for each of the 10,000 editions of LoTR""" + connector_info = models.Connector.objects.get(id=connector_id) + connector = load_connector(connector_info) + work = models.Work.objects.select_subclasses().get(id=work_id) + connector.create_edition_from_data(work, data) + + def load_connector(connector_info): """instantiate the connector class""" connector = importlib.import_module( diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index c13f4e3e6..3d5f913bd 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -5,7 +5,7 @@ from bookwyrm import models from bookwyrm.book_search import SearchResult from .abstract_connector import AbstractConnector, Mapping from .abstract_connector import get_data -from .connector_manager import ConnectorException +from .connector_manager import ConnectorException, create_edition_task class Connector(AbstractConnector): @@ -156,12 +156,16 @@ class Connector(AbstractConnector): for edition_uri in edition_options.get("uris"): remote_id = self.get_remote_id(edition_uri) - try: - data = self.get_book_data(remote_id) - except ConnectorException: - # who, indeed, knows - continue - self.create_edition_from_data(work, data) + create_edition_task.delay(self.connector.id, work.id, remote_id) + + def create_edition_from_data(self, work, edition_data, instance=None): + """pass in the url as data and then call the version in abstract connector""" + try: + data = self.get_book_data(edition_data) + except ConnectorException: + # who, indeed, knows + return + super().create_edition_from_data(work, data, instance=instance) def get_cover_url(self, cover_blob, *_): """format the relative cover url into an absolute one: diff --git a/bookwyrm/connectors/openlibrary.py b/bookwyrm/connectors/openlibrary.py index 2b625dffc..5288cc2be 100644 --- a/bookwyrm/connectors/openlibrary.py +++ b/bookwyrm/connectors/openlibrary.py @@ -5,7 +5,7 @@ from bookwyrm import models from bookwyrm.book_search import SearchResult from .abstract_connector import AbstractConnector, Mapping from .abstract_connector import get_data, infer_physical_format, unique_physical_format -from .connector_manager import ConnectorException +from .connector_manager import ConnectorException, create_edition_task from .openlibrary_languages import languages @@ -204,7 +204,7 @@ class Connector(AbstractConnector): # does this edition have ANY interesting data? if ignore_edition(edition_data): continue - self.create_edition_from_data(work, edition_data) + create_edition_task.delay(self.connector.id, work.id, edition_data) def ignore_edition(edition_data): From c738eaa2c2a04f8da4886bb4198063952891e8a3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 13:09:27 -0700 Subject: [PATCH 024/167] Use async requests for broadcasting When an activity needs to be broadcast to the whole wide fediverse, the number of requests can get enormous and the broadcast task ends up taking ages to run. This change sends these requests out in one aiohttp session, to improve performance. --- bookwyrm/models/activitypub_mixin.py | 57 +++++++++++++++++----------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 402cb040b..56f9da208 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -1,4 +1,5 @@ """ activitypub model functionality """ +import asyncio from base64 import b64encode from collections import namedtuple from functools import reduce @@ -6,9 +7,8 @@ import json import operator import logging from uuid import uuid4 -import requests -from requests.exceptions import RequestException +import aiohttp from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 @@ -510,15 +510,22 @@ def broadcast_task(sender_id, activity, recipients): """the celery task for broadcast""" user_model = apps.get_model("bookwyrm.User", require_ready=True) sender = user_model.objects.get(id=sender_id) - for recipient in recipients: - try: - sign_and_send(sender, activity, recipient) - except RequestException: - pass + asyncio.run(async_broadcast(recipients, sender, activity)) -def sign_and_send(sender, data, destination): - """crpyto whatever and http junk""" +async def async_broadcast(recipients, sender, data): + """Send all the broadcasts simultaneously""" + timeout = aiohttp.ClientTimeout(total=10) + async with aiohttp.ClientSession(timeout=timeout) as session: + tasks = [] + for recipient in recipients: + tasks.append( + asyncio.ensure_future(sign_and_send(session, sender, data, recipient)) + ) + + +async def sign_and_send(session, sender, data, destination): + """Sign the messages and send them in an asynchronous bundle""" now = http_date() if not sender.key_pair.private_key: @@ -526,21 +533,25 @@ def sign_and_send(sender, data, destination): raise ValueError("No private key found for sender") digest = make_digest(data) + headers = { + "Date": now, + "Digest": digest, + "Signature": make_signature(sender, destination, now, digest), + "Content-Type": "application/activity+json; charset=utf-8", + "User-Agent": USER_AGENT, + } - response = requests.post( - destination, - data=data, - headers={ - "Date": now, - "Digest": digest, - "Signature": make_signature(sender, destination, now, digest), - "Content-Type": "application/activity+json; charset=utf-8", - "User-Agent": USER_AGENT, - }, - ) - if not response.ok: - response.raise_for_status() - return response + try: + async with session.post(destination, data=data, headers=headers) as response: + if not response.ok: + logger.exception( + "Failed to send broadcast to %s: %s", destination, response.reason + ) + return await response + except asyncio.TimeoutError: + logger.info("Connection timed out for url: %s", destination) + except aiohttp.ClientError as err: + logger.exception(err) # pylint: disable=unused-argument From 077c9bfe46746b14bd992f349e7e676c5242ec20 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 31 May 2022 16:53:46 -0700 Subject: [PATCH 025/167] Updates locales for stopped reading strings --- locale/de_DE/LC_MESSAGES/django.mo | Bin 30883 -> 89936 bytes locale/de_DE/LC_MESSAGES/django.po | 58 +++++------ locale/en_US/LC_MESSAGES/django.po | 138 ++++++++++++++++++--------- locale/es_ES/LC_MESSAGES/django.mo | Bin 93859 -> 93859 bytes locale/es_ES/LC_MESSAGES/django.po | 58 +++++------ locale/fi_FI/LC_MESSAGES/django.mo | Bin 92620 -> 92620 bytes locale/fi_FI/LC_MESSAGES/django.po | 58 +++++------ locale/fr_FR/LC_MESSAGES/django.mo | Bin 44850 -> 96386 bytes locale/fr_FR/LC_MESSAGES/django.po | 58 +++++------ locale/gl_ES/LC_MESSAGES/django.mo | Bin 91831 -> 91831 bytes locale/gl_ES/LC_MESSAGES/django.po | 58 +++++------ locale/it_IT/LC_MESSAGES/django.mo | Bin 93253 -> 93253 bytes locale/it_IT/LC_MESSAGES/django.po | 58 +++++------ locale/lt_LT/LC_MESSAGES/django.mo | Bin 95566 -> 95566 bytes locale/lt_LT/LC_MESSAGES/django.po | 58 +++++------ locale/no_NO/LC_MESSAGES/django.mo | Bin 79314 -> 79314 bytes locale/no_NO/LC_MESSAGES/django.po | 58 +++++------ locale/pt_BR/LC_MESSAGES/django.mo | Bin 92485 -> 92485 bytes locale/pt_BR/LC_MESSAGES/django.po | 58 +++++------ locale/pt_PT/LC_MESSAGES/django.mo | Bin 86645 -> 86645 bytes locale/pt_PT/LC_MESSAGES/django.po | 58 +++++------ locale/ro_RO/LC_MESSAGES/django.mo | Bin 94710 -> 94710 bytes locale/ro_RO/LC_MESSAGES/django.po | 58 +++++------ locale/sv_SE/LC_MESSAGES/django.mo | Bin 92432 -> 92432 bytes locale/sv_SE/LC_MESSAGES/django.po | 58 +++++------ locale/zh_Hans/LC_MESSAGES/django.mo | Bin 44096 -> 86950 bytes locale/zh_Hans/LC_MESSAGES/django.po | 58 +++++------ locale/zh_Hant/LC_MESSAGES/django.mo | Bin 38839 -> 36001 bytes locale/zh_Hant/LC_MESSAGES/django.po | 58 +++++------ 29 files changed, 500 insertions(+), 450 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index 4ce83f72b3f3850c58528f13afcd23442a75a515..ccd061ca53329dcc362b7a17be946653965e94af 100644 GIT binary patch literal 89936 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\n" "Language-Team: German\n" "Language: de\n" @@ -121,25 +121,25 @@ msgstr "Gefahr" msgid "Automatically generated report" msgstr "Automatisch generierter Report" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Ausstehend" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Selbstlöschung" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Moderator*in suspendieren" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Moderator*in löschen" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Domainsperrung" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Speichern" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Das Laden von Daten wird eine Verbindung zu %(source_name)s aufbauen und überprüfen, ob Autor*in-Informationen vorliegen, die hier noch nicht bekannt sind. Bestehende Informationen werden nicht überschrieben." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "„%(book_title)s“ bearbeiten" msgid "Add Book" msgstr "Buch hinzufügen" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Buchinfo bestätigen" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Ist „%(name)s“ einer dieser Autor*innen?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autor*in von " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Weitere Informationen auf isni.org finden" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Neue*r Autor*in" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Als neue*r Autor*in erstellen: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Ist das eine Ausgabe eines vorhandenen Werkes?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Dies ist ein neues Werk." -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Zurück" @@ -1970,33 +1970,33 @@ msgstr "Bücher importieren" msgid "Data source:" msgstr "Datenquelle:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Du kannst deine Goodreads-Daten von der Import / Export-Seite deines Goodreads-Kontos downloaden." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Datei:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Besprechungen einschließen" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Datenschutzeinstellung für importierte Besprechungen:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importieren" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Zuletzt importiert" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Keine aktuellen Importe" @@ -5114,7 +5114,7 @@ msgstr "Datei überschreitet die maximale Größe von 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Keine gültige CSV-Datei" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index e776c8268..4b96725bf 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: 2022-05-23 21:04+0000\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -47,6 +47,10 @@ msgstr "" msgid "Reading finish date cannot be before start date." msgstr "" +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "" @@ -71,8 +75,8 @@ msgstr "" msgid "Book Title" msgstr "" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "" @@ -1076,7 +1080,7 @@ msgid "Add Another Author" msgstr "" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "" @@ -1710,13 +1714,13 @@ msgstr "" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "" @@ -1725,10 +1729,15 @@ msgstr "" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "" @@ -2056,8 +2065,8 @@ msgid "Row" msgstr "" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "" @@ -2070,8 +2079,8 @@ msgid "Openlibrary key" msgstr "" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "" @@ -2989,6 +2998,11 @@ msgstr "" msgid "Start \"%(book_title)s\"" msgstr "" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3013,6 +3027,7 @@ msgstr "" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "" @@ -3021,7 +3036,7 @@ msgstr "" msgid "Progress" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3035,23 +3050,27 @@ msgstr "" msgid "finished" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "" @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "" @@ -4737,6 +4761,17 @@ msgstr "" msgid "Start \"%(book_title)s\"" msgstr "" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "" @@ -4808,7 +4843,12 @@ msgstr "" msgid "More shelves" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "" @@ -4903,6 +4943,16 @@ msgstr "" msgid "reviewed %(book)s" msgstr "" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "" msgid "Edit profile" msgstr "" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "" diff --git a/locale/es_ES/LC_MESSAGES/django.mo b/locale/es_ES/LC_MESSAGES/django.mo index d108960bfa49e878cdc4f279ef13f34c3c5d38a7..ac3c879c224b7d0ec19c665c5026d0f1457921b1 100644 GIT binary patch delta 25 hcmZ2{mv!-7)(y2cxlDD9OcV?ZtqjaIx8IbR3IK<63CI8d delta 25 hcmZ2{mv!-7)(y2cxlDA84HOIwtPD&xx8IbR3IK;U3BmvX diff --git a/locale/es_ES/LC_MESSAGES/django.po b/locale/es_ES/LC_MESSAGES/django.po index 9d31c52d8..92dc13654 100644 --- a/locale/es_ES/LC_MESSAGES/django.po +++ b/locale/es_ES/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-30 10:04\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Spanish\n" "Language: es\n" @@ -121,25 +121,25 @@ msgstr "Cuidado" msgid "Automatically generated report" msgstr "Informe generado automáticamente" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Pendiente" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Auto-eliminación" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspensión de moderador" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Eliminación de moderador" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Bloqueo de dominio" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Guardar" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "La carga de datos se conectará a %(source_name)s y comprobará si hay metadatos sobre este autor que no están presentes aquí. Los metadatos existentes no serán sobrescritos." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Agregar libro" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirmar información de libro" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "¿Es \"%(name)s\" uno de estos autores?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autor/a de " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Más información en isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Este es un autor nuevo" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creando un autor nuevo: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "¿Es esta una edición de una obra ya existente?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Esta es una obra nueva" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Volver" @@ -1970,33 +1970,33 @@ msgstr "Importar libros" msgid "Data source:" msgstr "Fuente de datos:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Puedes descargar tus datos de Goodreads desde la página de importación/exportación de tu cuenta de Goodreads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Archivo de datos:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Incluir reseñas" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Configuración de privacidad para las reseñas importadas:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importar" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importaciones recientes" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "No hay ninguna importación reciente" @@ -5114,7 +5114,7 @@ msgstr "Archivo excede el tamaño máximo: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "No un archivo csv válido" diff --git a/locale/fi_FI/LC_MESSAGES/django.mo b/locale/fi_FI/LC_MESSAGES/django.mo index 91cf658f5016a3ec26cdf09513566445208c6f1d..a36c6c9337a59868d3f38cac2e617e96175c0262 100644 GIT binary patch delta 23 fcmX?enf1(N)(!PHIgCsc3=FLd%r>{*be#YIeMbq% delta 23 fcmX?enf1(N)(!PHISkAd3{9*|O*XgRbe#YIeT@mw diff --git a/locale/fi_FI/LC_MESSAGES/django.po b/locale/fi_FI/LC_MESSAGES/django.po index e2ceaad3d..0241e1e41 100644 --- a/locale/fi_FI/LC_MESSAGES/django.po +++ b/locale/fi_FI/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-05-07 14:54\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Finnish\n" "Language: fi\n" @@ -121,25 +121,25 @@ msgstr "Vaara" msgid "Automatically generated report" msgstr "Automaattisesti luotu raportti" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Odottaa" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Itse poistettu" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Moderaattorin estämä" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Moderaattorin poistama" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Verkkotunnuksen esto" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Tallenna" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Tietoja ladattaessa muodostetaan yhteys lähteeseen %(source_name)s ja sieltä haetaan metatietoja, joita ei vielä ole täällä. Olemassa olevia metatietoja ei korvata uusilla." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Muokkaa teosta ”%(book_title)s”" msgid "Add Book" msgstr "Lisää kirja" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Vahvista kirjan tiedot" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Onko ”%(name)s” joku seuraavista tekijöistä?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Tekijänä teoksessa " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Lisätietoja osoitteessa isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Uusi tekijä" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Luodaan uusi tekijä: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Onko tämä aiemmin lisätyn teoksen laitos?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Uusi teos" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Takaisin" @@ -1970,33 +1970,33 @@ msgstr "Tuo kirjoja" msgid "Data source:" msgstr "Tietolähde:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Goodreads-tiedot voi ladata Goodreads-käyttäjätilin Import/Export-sivun kautta." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Datatiedosto:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Myös arviot" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Tuotavien arvioiden yksityisyysvalinta:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Tuo" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Viimeksi tuotu" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Ei viimeaikaisia tuonteja" @@ -5114,7 +5114,7 @@ msgstr "Tiedosto on enimmäiskokoa 10 Mt suurempi" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Epäkelpo csv-tiedosto" diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 4cdcbf8ea2a3ffdeed740317a055f435e5954b7c..1414a05541850774156dd0c1b35482baaca20e5d 100644 GIT binary patch literal 96386 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 literal 44850 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\n" "Language-Team: French\n" "Language: fr\n" @@ -121,25 +121,25 @@ msgstr "Danger" msgid "Automatically generated report" msgstr "Rapport généré automatiquement" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "En attente" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Auto-suppression" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspension du modérateur" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Suppression du modérateur" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Blocage de domaine" @@ -734,7 +734,7 @@ msgstr "ISNI :" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Enregistrer" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Le chargement des données se connectera à %(source_name)s et vérifiera les métadonnées de cet auteur ou autrice qui ne sont pas présentes ici. Les métadonnées existantes ne seront pas écrasées." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Modifier « %(book_title)s »" msgid "Add Book" msgstr "Ajouter un livre" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirmer les informations de ce livre" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Est-ce que \"%(name)s\" fait partie de ces auteurs ou autrices ?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Auteur ou autrice de " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Trouver plus d’informations sur isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Il s’agit d’un nouvel auteur ou d’une nouvelle autrice." -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Création d’un nouvel auteur/autrice : %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Est‑ce l’édition d’un ouvrage existant ?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Il s’agit d’un nouvel ouvrage." -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Retour" @@ -1970,33 +1970,33 @@ msgstr "Importer des livres" msgid "Data source:" msgstr "Source de données :" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Vous pouvez télécharger vos données Goodreads depuis la page Import/Export de votre compte Goodreads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Fichier de données :" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Importer les critiques" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Confidentialité des critiques importées :" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importer" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importations récentes" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Aucune importation récente" @@ -5114,7 +5114,7 @@ msgstr "Ce fichier dépasse la taille limite : 10 Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Fichier CSV non valide" diff --git a/locale/gl_ES/LC_MESSAGES/django.mo b/locale/gl_ES/LC_MESSAGES/django.mo index 94b9ad7671769593d3a617ccd92bd9ddca99cd18..7f76d9eef71720793e7517b3f59f9bb4709b56a8 100644 GIT binary patch delta 25 hcmdmfmUa7C)(y2cxlDD9OcV?ZtqjaIx8F4A1ptU}3EThx delta 25 hcmdmfmUa7C)(y2cxlD8oEENn*tPG4cx8F4A1ptVU3Eltz diff --git a/locale/gl_ES/LC_MESSAGES/django.po b/locale/gl_ES/LC_MESSAGES/django.po index 8d05e8d93..13ae25253 100644 --- a/locale/gl_ES/LC_MESSAGES/django.po +++ b/locale/gl_ES/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-09 14:02\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Galician\n" "Language: gl\n" @@ -121,25 +121,25 @@ msgstr "Perigo" msgid "Automatically generated report" msgstr "Denuncia creada automáticamente" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Pendente" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Auto eliminación" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspendido pola moderación" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Eliminado pola moderación" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Bloqueo de dominio" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Gardar" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Ao cargar os datos vas conectar con %(source_name)s e comprobar se existen metadatos desta persoa autora que non están aquí presentes. Non se sobrescribirán os datos existentes." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Engadir libro" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirma info do libro" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "É \"%(name)s\" un destas autoras?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autora de " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Atopa máis información en isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Esta é unha nova autora" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creando nova autora: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "É esta a edición dun traballo existente?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Este é un novo traballo" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Atrás" @@ -1970,33 +1970,33 @@ msgstr "Importar libros" msgid "Data source:" msgstr "Fonte de datos:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Podes descargar os teus datos de Goodreads desde a páxina de Exportación/Importación da túa conta Goodreads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Ficheiro de datos:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Incluír recensións" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Axuste de privacidade para recensións importadas:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importar" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importacións recentes" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Sen importacións recentes" @@ -5114,7 +5114,7 @@ msgstr "O ficheiro supera o tamaño máximo: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Non é un ficheiro csv válido" diff --git a/locale/it_IT/LC_MESSAGES/django.mo b/locale/it_IT/LC_MESSAGES/django.mo index df949ed1c75517787badd903073f12e377497711..25657558b66666de4c3e924b32accca50c522b3f 100644 GIT binary patch delta 25 hcmX?lgZ1bQ)(y2cxlDD9OcV?ZtqjaIx8K}12>^}~3ZVc1 delta 25 hcmX?lgZ1bQ)(y2cxlDA83>1uvtV}F7x8K}12>^~B3Z?)6 diff --git a/locale/it_IT/LC_MESSAGES/django.po b/locale/it_IT/LC_MESSAGES/django.po index 80b09cbe6..5e53007b2 100644 --- a/locale/it_IT/LC_MESSAGES/django.po +++ b/locale/it_IT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-20 22:49\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Italian\n" "Language: it\n" @@ -121,25 +121,25 @@ msgstr "Attenzione" msgid "Automatically generated report" msgstr "Rapporto generato automaticamente" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "In attesa" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Eliminazione automatica" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Sospensione del moderatore" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Cancellazione del moderatore" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Blocco del dominio" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Salva" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Il caricamento dei dati si collegherà a %(source_name)s e verificherà eventuali metadati relativi a questo autore che non sono presenti qui. I metadati esistenti non vengono sovrascritti." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Modifica \"%(book_title)s\"" msgid "Add Book" msgstr "Aggiungi libro" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Conferma informazioni sul libro" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "È \"%(name)s\" uno di questi autori?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autore di " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Trova maggiori informazioni su isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Questo è un nuovo autore" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creazione di un nuovo autore: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "È un'edizione di un'opera esistente?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Si tratta di un nuovo lavoro" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Indietro" @@ -1970,33 +1970,33 @@ msgstr "Importa libri" msgid "Data source:" msgstr "Sorgenti dati:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Puoi scaricare i tuoi dati Goodreads dalla pagina \"Importa/Esporta\" del tuo account Goodreads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Dati file:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Includi recensioni" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Impostazione della privacy per le recensioni importate:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importa" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importazioni recenti" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Nessuna importazione recente" @@ -5114,7 +5114,7 @@ msgstr "Il file supera la dimensione massima: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Non è un file di csv valido" diff --git a/locale/lt_LT/LC_MESSAGES/django.mo b/locale/lt_LT/LC_MESSAGES/django.mo index 034db68595e2d9de93e752d0360b2007e2900104..cccee2cfc7740a9e736856d27b0052d4492deca3 100644 GIT binary patch delta 25 hcmX^2iuK$p)(y2cxlDD9OcV?ZtqjaIx8FQI8vv623h4j< delta 25 hcmX^2iuK$p)(y2cxlD8o4HOK_txQcex8FQI8vv633hV#? diff --git a/locale/lt_LT/LC_MESSAGES/django.po b/locale/lt_LT/LC_MESSAGES/django.po index a5bb31df0..a2a83ca86 100644 --- a/locale/lt_LT/LC_MESSAGES/django.po +++ b/locale/lt_LT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-10 07:54\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Lithuanian\n" "Language: lt\n" @@ -121,25 +121,25 @@ msgstr "Pavojus" msgid "Automatically generated report" msgstr "Automatiškai sugeneruota ataskaita" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Laukiama" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Išsitrina savaime" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Moderatorius nutraukė" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Moderatorius ištrynė" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Blokuoti pagal domeną" @@ -742,7 +742,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -765,8 +765,8 @@ msgstr "Išsaugoti" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -788,7 +788,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Duomenų įkėlimas prisijungs prie %(source_name)s ir patikrins ar nėra naujos informacijos. Esantys metaduomenys nebus perrašomi." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -961,42 +961,42 @@ msgstr "Redaguoti „%(book_title)s“" msgid "Add Book" msgstr "Pridėti knygą" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Patvirtinti knygos informaciją" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Ar \"%(name)s\" yra vienas iš šių autorių?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autorius " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Daugiau informacijos isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Tai naujas autorius" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Kuriamas naujas autorius: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Ar tai egzistuojančio darbo leidimas?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Tai naujas darbas" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Atgal" @@ -1990,33 +1990,33 @@ msgstr "Importuoti knygas" msgid "Data source:" msgstr "Duomenų šaltinis:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Galite atsisiųsti savo „Goodreads“ duomenis iš Importavimo ir eksportavimo puslapio, esančio jūsų „Goodreads“ paskyroje." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Duomenų failas:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Įtraukti atsiliepimus" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Privatumo nustatymai svarbiems atsiliepimams:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importuoti" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Pastaruoju metu importuota" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Pastaruoju metu neimportuota" @@ -5164,7 +5164,7 @@ msgstr "Failas viršijo maksimalų dydį: 10 MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Netinkamas csv failas" diff --git a/locale/no_NO/LC_MESSAGES/django.mo b/locale/no_NO/LC_MESSAGES/django.mo index 8df82422a7b568c2600bf83432194b9d511b36fa..5ed2511ca983f6df576a7eecf3a41cbd3f52325e 100644 GIT binary patch delta 25 hcmccgn&r}KmJJ*CbD8QInJ5?-S{aya-o0PE3;>j;3Qzz5 delta 25 hcmccgn&r}KmJJ*CbD8KGSST17TA3Pb-o0PE3;>kD3Q_<7 diff --git a/locale/no_NO/LC_MESSAGES/django.po b/locale/no_NO/LC_MESSAGES/django.po index 21cd784c6..3d94300af 100644 --- a/locale/no_NO/LC_MESSAGES/django.po +++ b/locale/no_NO/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-08 21:50\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Norwegian\n" "Language: no\n" @@ -121,25 +121,25 @@ msgstr "" msgid "Automatically generated report" msgstr "" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Avventer" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Selvsletting" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Moderatør suspensjon" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Moderatør sletting" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Domeneblokkering" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Lagre" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Laster inn data kobler til %(source_name)s og finner metadata om denne forfatteren som enda ikke finnes her. Eksisterende metadata vil ikke bli overskrevet." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Rediger \"%(book_title)s" msgid "Add Book" msgstr "Legg til bok" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Bekreft bokinformasjon" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Er \"%(name)s\" en av disse forfatterne?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Forfatter av " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Finn mer informasjon på isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Dette er en ny forfatter" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Oppretter en ny forfatter: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Er dette en utgave av et eksisterende verk?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Dette er et nytt verk" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Tilbake" @@ -1970,33 +1970,33 @@ msgstr "Importer bøker" msgid "Data source:" msgstr "Datakilde:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Du kan laste ned Goodread-dataene dine fra Import/Export sida på Goodread-kontoen din." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Datafil:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Inkluder anmeldelser" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Personverninnstilling for importerte anmeldelser:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importér" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Nylig importer" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Ingen nylige importer" @@ -5112,7 +5112,7 @@ msgstr "Filen overskrider maksimal størrelse: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Ikke en gyldig csv-fil" diff --git a/locale/pt_BR/LC_MESSAGES/django.mo b/locale/pt_BR/LC_MESSAGES/django.mo index 88416d0ef1ee11c1448546b7531ef935f76c9ccb..a67f03752977dd5bf848eb84e8426cff2b52f4c2 100644 GIT binary patch delta 25 hcmX?liS_6u)(y2cxlDD9OcV?ZtqjaIx8K~?4*-n;3X%W- delta 25 hcmX?liS_6u)(y2cxlD8oEEJ54tqhGex8K~?4*-oF3X}i< diff --git a/locale/pt_BR/LC_MESSAGES/django.po b/locale/pt_BR/LC_MESSAGES/django.po index 617f15811..371e46ec6 100644 --- a/locale/pt_BR/LC_MESSAGES/django.po +++ b/locale/pt_BR/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-08 23:12\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Portuguese, Brazilian\n" "Language: pt\n" @@ -121,25 +121,25 @@ msgstr "Perigo" msgid "Automatically generated report" msgstr "Relatório gerado automaticamente" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Pendente" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Autoexclusão" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspensão de moderador" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Exclusão de moderador" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Bloqueio de domínio" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Salvar" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Para carregar informações nos conectaremos a %(source_name)s e buscaremos metadados que ainda não temos sobre este/a autor/a. Metadados já existentes não serão substituídos." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Adicionar livro" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirmar informações do livro" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "\"%(name)s\" é uma das pessoas citadas abaixo?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autor/a de " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Conheça mais em isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "É um/a novo/a autor/a" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Criando um/a novo/a autor/a: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "É uma edição de uma obra já registrada?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "É uma nova obra" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Voltar" @@ -1970,33 +1970,33 @@ msgstr "Importar livros" msgid "Data source:" msgstr "Fonte dos dados:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Você pode baixar seus dados do Goodreads na página de Importar/Exportar da sua conta." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Arquivo de dados:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Incluir resenhas" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Configurações de privacidade para resenhas importadas:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importar" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importações recentes" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Nenhuma importação recente" @@ -5114,7 +5114,7 @@ msgstr "Arquivo excede o tamanho máximo: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Não é um arquivo csv válido" diff --git a/locale/pt_PT/LC_MESSAGES/django.mo b/locale/pt_PT/LC_MESSAGES/django.mo index ad1072d56454e18c3a50ed80261ad52c471dcaa8..640fa53364f694b3920832f90c1245d5261bcb29 100644 GIT binary patch delta 23 fcmeymg!StZ)(ugoIgCsc3=FLd%r+;T7H$UscvcA; delta 23 fcmeymg!StZ)(ugoISkAcjEt>}%r_^U7H$Usc#a7o diff --git a/locale/pt_PT/LC_MESSAGES/django.po b/locale/pt_PT/LC_MESSAGES/django.po index 844605068..fa7c865aa 100644 --- a/locale/pt_PT/LC_MESSAGES/django.po +++ b/locale/pt_PT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-05-06 23:27\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Portuguese\n" "Language: pt\n" @@ -121,25 +121,25 @@ msgstr "Perigo" msgid "Automatically generated report" msgstr "Relatório gerado automaticamente" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Pendente" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Auto-exclusão" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspensão do moderador" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Exclusão do moderador" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Bloqueio de domínio" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Salvar" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Carregar os dados irá conectar a %(source_name)s e verificar se há metadados sobre este autor que não estão aqui presentes. Os metadados existentes não serão substituídos." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Adicionar um Livro" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirmar informações do livro" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "\"%(name)s\" é um destes autores?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autor de " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Podes encontrar mais informações em isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Este é um novo autor" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Criar um novo autor: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Esta é uma edição de um trabalho existente?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Este é um novo trabalho" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Voltar" @@ -1970,33 +1970,33 @@ msgstr "Importar livros" msgid "Data source:" msgstr "Origem dos dados:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Podes fazer download dos teus dados do Goodreads na Importar/Exportar página da tua conta do Goodreads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Ficheiro de dados:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Incluir criticas" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Configuração de privacidade para criticas importadas:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importar" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importações recentes" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Nenhuma importação recente" @@ -5114,7 +5114,7 @@ msgstr "Ficheiro excede o tamanho máximo: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Não é um ficheiro csv válido" diff --git a/locale/ro_RO/LC_MESSAGES/django.mo b/locale/ro_RO/LC_MESSAGES/django.mo index f64e15d56941a5d05dba5a360a979b9346f9db05..e9b278ecbb2e3d98a75cc249f521826394ea599b 100644 GIT binary patch delta 23 fcmezNnDyIZ)(!PHIgCsc3=FLd%r>{*%%1@Ohd~N% delta 23 fcmezNnDyIZ)(!PHISkDdj0~*|jW@U7%%1@OhgAx1 diff --git a/locale/ro_RO/LC_MESSAGES/django.po b/locale/ro_RO/LC_MESSAGES/django.po index 48fd49161..8d20397dd 100644 --- a/locale/ro_RO/LC_MESSAGES/django.po +++ b/locale/ro_RO/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-05-16 21:13\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Romanian\n" "Language: ro\n" @@ -121,25 +121,25 @@ msgstr "Pericol" msgid "Automatically generated report" msgstr "Raport generat automat" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "În așteptare" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Ștergere automată" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Suspendat de moderator" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Șters de moderator" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Blocat de domeniu" @@ -738,7 +738,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -761,8 +761,8 @@ msgstr "Salvați" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -784,7 +784,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Încărcatul de date se va conecta la %(source_name)s și verifica orice metadate despre autor care nu sunt prezente aici. Metadatele existente nu vor fi suprascrise." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -955,42 +955,42 @@ msgstr "Editați „%(book_title)s”" msgid "Add Book" msgstr "Adăugați carte" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Confirmați informațiile cărții" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Este „%(name)s” unul dintre acești autori?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Autor al " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Aflați mai multe la isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Acesta este un autor nou" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creați un autor nou: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Este această o ediție a unei opere existente?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Aceasta este o operă nouă" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Înapoi" @@ -1980,33 +1980,33 @@ msgstr "Importați cărți" msgid "Data source:" msgstr "Sursa de date:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Puteți descărca datele dvs. GoodReads de pe pagina Import/Export a contului dvs. GoodReads." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Fișierul de date:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Includeți recenzii" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Setare de confidențialitate pentru recenziile importate:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importați" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Importuri recente" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Niciun import recent" @@ -5139,7 +5139,7 @@ msgstr "Fișierul depășește dimensiuneaz maximă: 10Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Nu este un fișier csv valid" diff --git a/locale/sv_SE/LC_MESSAGES/django.mo b/locale/sv_SE/LC_MESSAGES/django.mo index 70fc627ef844b901dddf4a7d75e721719fa7cb70..0779ff8e38ab3604aaefede79a801676e6d7ed26 100644 GIT binary patch delta 25 hcmbPmiFLvy)(xCDxlDD9OcV?ZtqjaI3*Y?P4*+@034Z_p delta 25 hcmbPmiFLvy)(xCDxlD8oEEJ3ktxOFz3*Y?P4*+@Q34s6r diff --git a/locale/sv_SE/LC_MESSAGES/django.po b/locale/sv_SE/LC_MESSAGES/django.po index 0ff609298..880919874 100644 --- a/locale/sv_SE/LC_MESSAGES/django.po +++ b/locale/sv_SE/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-08 21:50\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Swedish\n" "Language: sv\n" @@ -121,25 +121,25 @@ msgstr "Observera" msgid "Automatically generated report" msgstr "Automatiskt genererad rapport" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "Pågående" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "Självborttagning" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "Moderator-avstängning" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "Borttagning av moderator" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "Domänblockering" @@ -734,7 +734,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -757,8 +757,8 @@ msgstr "Spara" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -780,7 +780,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "Att ladda in data kommer att ansluta till %(source_name)s och kontrollera eventuella metadata om den här författaren som inte finns här. Befintliga metadata kommer inte att skrivas över." #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -949,42 +949,42 @@ msgstr "Redigera \"%(book_title)s\"" msgid "Add Book" msgstr "Lägg till bok" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "Bekräfta bokens info" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "Är \"%(name)s\" en utav dessa författare?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "Författare av " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "Hitta mer information på isni.org" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "Det här är en ny författare" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "Skapar en ny författare: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "Är det här en version av ett redan befintligt verk?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "Det här är ett nytt verk" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "Bakåt" @@ -1970,33 +1970,33 @@ msgstr "Importera böcker" msgid "Data source:" msgstr "Datakälla:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "Du kan ladda ner Goodreads-data från Import/Export-sidan på ditt Goodreads-konto." -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "Datafil:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "Inkludera recensioner" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "Integritetsinställning för importerade recensioner:" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "Importera" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "Senaste importer" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "Ingen importering nyligen" @@ -5114,7 +5114,7 @@ msgstr "Filen överskrider maximal storlek: 10 MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "Inte en giltig csv-fil" diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index 1d1227f8092b70c68bb692fb532759090142aa83..4c2a6c1f556905de752d63e136b4b7d802a1c56c 100644 GIT binary patch literal 86950 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≻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 QRs`Iq`R1l-oh0@D0YazD0ssI2 literal 44096 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 S0TOg?KN0&d0;IH0jQ%f4%`RX7 diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index b1b37dc3d..8bd28ceab 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-08 21:00+0000\n" -"PO-Revision-Date: 2022-04-29 14:20\n" +"POT-Creation-Date: 2022-05-23 21:04+0000\n" +"PO-Revision-Date: 2022-05-24 01:06\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Chinese Simplified\n" "Language: zh\n" @@ -121,25 +121,25 @@ msgstr "危险" msgid "Automatically generated report" msgstr "自动生成的举报" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "待处理" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "自我删除" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "仲裁员停用" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "仲裁员删除" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "域名屏蔽" @@ -730,7 +730,7 @@ msgstr "ISNI:" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -753,8 +753,8 @@ msgstr "保存" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -776,7 +776,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "加载数据会连接到 %(source_name)s 并检查这里还没有记录的与作者相关的元数据。现存的元数据不会被覆盖。" #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -943,42 +943,42 @@ msgstr "编辑《%(book_title)s》" msgid "Add Book" msgstr "添加书目" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "确认书目信息" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "“%(name)s” 是这些作者之一吗?" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "所著书有 " -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "在 isni.org 查找更多信息" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "这是一位新的作者" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "正在创建新的作者: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "这是已存在的作品的一个版本吗?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "这是一个新的作品。" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "返回" @@ -1960,33 +1960,33 @@ msgstr "导入书目" msgid "Data source:" msgstr "数据来源:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "您可以从 Import/Export page 下载或导出您的 Goodread 数据。" -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "数据文件:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "纳入书评" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "导入书评的隐私设定" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "导入" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "最近的导入" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "无最近的导入" @@ -5089,7 +5089,7 @@ msgstr "文件超过了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "不是有效的 csv 文件" diff --git a/locale/zh_Hant/LC_MESSAGES/django.mo b/locale/zh_Hant/LC_MESSAGES/django.mo index f9ca27be9b891b3b13c30e68d084e0cd54184a43..20be041a8670213f5d046504898a50751bba77e8 100644 GIT binary patch delta 13136 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 delta 15265 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\n" "Language-Team: Chinese Traditional\n" "Language: zh\n" @@ -121,25 +121,25 @@ msgstr "" msgid "Automatically generated report" msgstr "" -#: bookwyrm/models/base_model.py:17 bookwyrm/models/link.py:72 +#: bookwyrm/models/base_model.py:18 bookwyrm/models/link.py:72 #: bookwyrm/templates/import/import_status.html:200 #: bookwyrm/templates/settings/link_domains/link_domains.html:19 msgid "Pending" msgstr "" -#: bookwyrm/models/base_model.py:18 +#: bookwyrm/models/base_model.py:19 msgid "Self deletion" msgstr "" -#: bookwyrm/models/base_model.py:19 +#: bookwyrm/models/base_model.py:20 msgid "Moderator suspension" msgstr "" -#: bookwyrm/models/base_model.py:20 +#: bookwyrm/models/base_model.py:21 msgid "Moderator deletion" msgstr "" -#: bookwyrm/models/base_model.py:21 +#: bookwyrm/models/base_model.py:22 msgid "Domain block" msgstr "" @@ -730,7 +730,7 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:115 #: bookwyrm/templates/book/book.html:202 -#: bookwyrm/templates/book/edit/edit_book.html:127 +#: bookwyrm/templates/book/edit/edit_book.html:135 #: bookwyrm/templates/book/file_links/add_link_modal.html:60 #: bookwyrm/templates/book/file_links/edit_links.html:82 #: bookwyrm/templates/groups/form.html:32 @@ -753,8 +753,8 @@ msgstr "儲存" #: bookwyrm/templates/author/sync_modal.html:23 #: bookwyrm/templates/book/book.html:203 #: bookwyrm/templates/book/cover_add_modal.html:33 -#: bookwyrm/templates/book/edit/edit_book.html:129 -#: bookwyrm/templates/book/edit/edit_book.html:132 +#: bookwyrm/templates/book/edit/edit_book.html:137 +#: bookwyrm/templates/book/edit/edit_book.html:140 #: bookwyrm/templates/book/file_links/add_link_modal.html:59 #: bookwyrm/templates/book/file_links/verification_modal.html:25 #: bookwyrm/templates/book/sync_modal.html:23 @@ -776,7 +776,7 @@ msgid "Loading data will connect to %(source_name)s and check f msgstr "" #: bookwyrm/templates/author/sync_modal.html:24 -#: bookwyrm/templates/book/edit/edit_book.html:114 +#: bookwyrm/templates/book/edit/edit_book.html:122 #: bookwyrm/templates/book/sync_modal.html:24 #: bookwyrm/templates/groups/members.html:29 #: bookwyrm/templates/landing/password_reset.html:42 @@ -943,42 +943,42 @@ msgstr "編輯 \"%(book_title)s\"" msgid "Add Book" msgstr "新增書目" -#: bookwyrm/templates/book/edit/edit_book.html:54 +#: bookwyrm/templates/book/edit/edit_book.html:62 msgid "Confirm Book Info" msgstr "確認書目資料" -#: bookwyrm/templates/book/edit/edit_book.html:62 +#: bookwyrm/templates/book/edit/edit_book.html:70 #, python-format msgid "Is \"%(name)s\" one of these authors?" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:73 -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:81 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Author of " msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:83 msgid "Find more information at isni.org" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:85 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "This is a new author" msgstr "這是一位新的作者" -#: bookwyrm/templates/book/edit/edit_book.html:92 +#: bookwyrm/templates/book/edit/edit_book.html:100 #, python-format msgid "Creating a new author: %(name)s" msgstr "正在建立新的作者: %(name)s" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:107 msgid "Is this an edition of an existing work?" msgstr "這是已存在的作品的另一個版本嗎?" -#: bookwyrm/templates/book/edit/edit_book.html:107 +#: bookwyrm/templates/book/edit/edit_book.html:115 msgid "This is a new work" msgstr "這是一個新的作品。" -#: bookwyrm/templates/book/edit/edit_book.html:116 +#: bookwyrm/templates/book/edit/edit_book.html:124 #: bookwyrm/templates/feed/status.html:21 msgid "Back" msgstr "返回" @@ -1960,33 +1960,33 @@ msgstr "匯入書目" msgid "Data source:" msgstr "資料來源:" -#: bookwyrm/templates/import/import.html:39 +#: bookwyrm/templates/import/import.html:42 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." msgstr "" -#: bookwyrm/templates/import/import.html:44 +#: bookwyrm/templates/import/import.html:47 msgid "Data file:" msgstr "資料檔案:" -#: bookwyrm/templates/import/import.html:52 +#: bookwyrm/templates/import/import.html:55 msgid "Include reviews" msgstr "納入書評" -#: bookwyrm/templates/import/import.html:57 +#: bookwyrm/templates/import/import.html:60 msgid "Privacy setting for imported reviews:" msgstr "匯入書評的隱私設定" -#: bookwyrm/templates/import/import.html:63 +#: bookwyrm/templates/import/import.html:66 #: bookwyrm/templates/preferences/layout.html:31 #: bookwyrm/templates/settings/federation/instance_blocklist.html:76 msgid "Import" msgstr "匯入" -#: bookwyrm/templates/import/import.html:68 +#: bookwyrm/templates/import/import.html:71 msgid "Recent Imports" msgstr "最近的匯入" -#: bookwyrm/templates/import/import.html:70 +#: bookwyrm/templates/import/import.html:73 msgid "No recent imports" msgstr "無最近的匯入" @@ -5087,7 +5087,7 @@ msgstr "檔案超過了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/imports/import_data.py:67 +#: bookwyrm/views/imports/import_data.py:70 msgid "Not a valid csv file" msgstr "不是有效的 csv 檔案" From 4de9989d8e88d45de260d7aeb07ded7612d5bd28 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 5 Jun 2022 16:02:25 +1000 Subject: [PATCH 026/167] add page numbers to comment and quote statuses This adds the page number for quote and comment statuses where a page number is provided: - all ActivityPub posts - Explore cards for comments (quotes already have the page number) This responds to #2136 --- bookwyrm/models/status.py | 30 ++++++++++++++----- .../snippets/status/content_status.html | 3 ++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index f37076b5c..3949e09a9 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -303,10 +303,17 @@ class Comment(BookStatus): @property def pure_content(self): """indicate the book in question for mastodon (or w/e) users""" - return ( - f'{self.content}

(comment on ' - f'"{self.book.title}")

' - ) + if self.progress_mode == "PG" and self.progress and (self.progress > 0): + return_value = ( + f'{self.content}

(comment on ' + f'"{self.book.title}", page {self.progress})

' + ) + else: + return_value = ( + f'{self.content}

(comment on ' + f'"{self.book.title}")

' + ) + return return_value activity_serializer = activitypub.Comment @@ -332,10 +339,17 @@ class Quotation(BookStatus): """indicate the book in question for mastodon (or w/e) users""" quote = re.sub(r"^

", '

"', self.quote) quote = re.sub(r"

$", '"

', quote) - return ( - f'{quote}

-- ' - f'"{self.book.title}"

{self.content}' - ) + if self.position_mode == "PG" and self.position and (self.position > 0): + return_value = ( + f'{quote}

-- ' + f'"{self.book.title}", page {self.position}

{self.content}' + ) + else: + return_value = ( + f'{quote}

-- ' + f'"{self.book.title}"

{self.content}' + ) + return return_value activity_serializer = activitypub.Quotation diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html index bee4af1dc..d0d385153 100644 --- a/bookwyrm/templates/snippets/status/content_status.html +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -112,6 +112,9 @@ {% with full=status.content|safe no_trim=status.content_warning itemprop="reviewBody" %} {% include 'snippets/trimmed_text.html' %} {% endwith %} + {% if status.progress %} +
{% trans "page" %} {{ status.progress }}
+ {% endif %} {% endif %} {% if status.attachments.exists %} From 482005f3049ba8a1c533983f5751b18e1f6ba3fe Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Sun, 5 Jun 2022 20:03:36 +0000 Subject: [PATCH 027/167] Update preview image generation to only query ids Previously we were querying the full book objects just to get a list of id's, which is much slower and also takes a lot more memory, which can cause the process to be killed on memory-limited machines with a large number of books. Instead, since we're just dispatching jobs here, we can just ask for the id's, which is faster and much more practical memory-wise. The map is a little annoying, I didn't see a way to directly get just a list of the value of one field, so we have to get a list of dictionairies with one key and then pull that key out. Whatevs. --- bookwyrm/management/commands/generate_preview_images.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/management/commands/generate_preview_images.py b/bookwyrm/management/commands/generate_preview_images.py index 0454e5e51..b00fafb10 100644 --- a/bookwyrm/management/commands/generate_preview_images.py +++ b/bookwyrm/management/commands/generate_preview_images.py @@ -56,12 +56,12 @@ class Command(BaseCommand): self.stdout.write(" OK 🖼") # Books - books = models.Book.objects.select_subclasses().filter() + book_ids = [values["id"] for values in models.Book.objects.select_subclasses().filter().values('id')] self.stdout.write( - " → Book preview images ({}): ".format(len(books)), ending="" + " → Book preview images ({}): ".format(len(book_ids)), ending="" ) - for book in books: - preview_images.generate_edition_preview_image_task.delay(book.id) + for book_id in book_ids: + preview_images.generate_edition_preview_image_task.delay(book_id) self.stdout.write(".", ending="") self.stdout.write(" OK 🖼") From b744ff7836dbf4e42b52ccd4d6ddb747270009d8 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Sun, 5 Jun 2022 13:40:01 -0700 Subject: [PATCH 028/167] Run black --- bookwyrm/management/commands/generate_preview_images.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bookwyrm/management/commands/generate_preview_images.py b/bookwyrm/management/commands/generate_preview_images.py index b00fafb10..7952803d8 100644 --- a/bookwyrm/management/commands/generate_preview_images.py +++ b/bookwyrm/management/commands/generate_preview_images.py @@ -56,7 +56,12 @@ class Command(BaseCommand): self.stdout.write(" OK 🖼") # Books - book_ids = [values["id"] for values in models.Book.objects.select_subclasses().filter().values('id')] + book_ids = [ + values["id"] + for values in models.Book.objects.select_subclasses() + .filter() + .values("id") + ] self.stdout.write( " → Book preview images ({}): ".format(len(book_ids)), ending="" ) From 6d6ab9a53193b20ba3f2e6d8691fc50f287616d0 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Sun, 5 Jun 2022 14:38:03 -0700 Subject: [PATCH 029/167] Add .pylintrc with fixes for new pylint version --- .pylintrc | 6 ++++++ bookwyrm/tests/connectors/test_openlibrary_connector.py | 2 +- bookwyrm/tests/models/test_import_model.py | 2 +- bookwyrm/tests/views/test_status.py | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 000000000..7f92d0168 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,6 @@ +[MAIN] +ignore=migrations +load-plugins=pylint.extensions.no_self_use + +[MESSAGES CONTROL] +disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406,R0401,R0801,C3001 diff --git a/bookwyrm/tests/connectors/test_openlibrary_connector.py b/bookwyrm/tests/connectors/test_openlibrary_connector.py index c05eb1a94..8f81b2073 100644 --- a/bookwyrm/tests/connectors/test_openlibrary_connector.py +++ b/bookwyrm/tests/connectors/test_openlibrary_connector.py @@ -229,7 +229,7 @@ class Openlibrary(TestCase): status=200, ) with patch( - "bookwyrm.connectors.openlibrary.Connector." "get_authors_from_data" + "bookwyrm.connectors.openlibrary.Connector.get_authors_from_data" ) as mock: mock.return_value = [] result = self.connector.create_edition_from_data(work, self.edition_data) diff --git a/bookwyrm/tests/models/test_import_model.py b/bookwyrm/tests/models/test_import_model.py index 7cecfe416..d1ff209f4 100644 --- a/bookwyrm/tests/models/test_import_model.py +++ b/bookwyrm/tests/models/test_import_model.py @@ -195,7 +195,7 @@ class ImportJob(TestCase): ) as search: search.return_value = result with patch( - "bookwyrm.connectors.openlibrary.Connector." "get_authors_from_data" + "bookwyrm.connectors.openlibrary.Connector.get_authors_from_data" ): book = item.get_book_from_identifier() diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 355071573..0026c52b5 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -281,7 +281,7 @@ http://www.fish.com/""" result = views.status.to_markdown(text) self.assertEqual( result, - '

hi and fish.com ' "is rad

", + '

hi and fish.com is rad

', ) def test_to_markdown_detect_url(self, *_): @@ -297,7 +297,7 @@ http://www.fish.com/""" """this is mostly handled in other places, but nonetheless""" text = "[hi](http://fish.com) is rad" result = views.status.to_markdown(text) - self.assertEqual(result, '

hi ' "is rad

") + self.assertEqual(result, '

hi is rad

') def test_delete_status(self, mock, *_): """marks a status as deleted""" From b3603c04c54d67eb9e8d81737fc940c476d0101b Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Sun, 5 Jun 2022 14:49:21 -0700 Subject: [PATCH 030/167] Add pylint to bw-dev Because pylint requires the app to be fully parseable with all its dependencies, we run it in the web container, and add pylint as a dev dependency. --- Dockerfile | 6 +++++- bw-dev | 5 +++++ requirements.dev.txt | 7 +++++++ requirements.txt | 8 -------- 4 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 requirements.dev.txt diff --git a/Dockerfile b/Dockerfile index 349dd82b1..99a25768b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,10 @@ RUN mkdir /app /app/static /app/images WORKDIR /app +RUN apt-get update && apt-get install -y gettext libgettextpo-dev tidy && apt-get clean + COPY requirements.txt /app/ RUN pip install -r requirements.txt --no-cache-dir -RUN apt-get update && apt-get install -y gettext libgettextpo-dev tidy && apt-get clean + +COPY requirements.dev.txt /app/ +RUN pip install -r requirements.dev.txt --no-cache-dir diff --git a/bw-dev b/bw-dev index 058f2639b..4dd543c0a 100755 --- a/bw-dev +++ b/bw-dev @@ -140,6 +140,10 @@ case "$CMD" in black) docker-compose run --rm dev-tools black celerywyrm bookwyrm ;; + pylint) + # pylint depends on having the app dependencies in place, so we run it in the web container + runweb pylint bookwyrm/ + ;; prettier) docker-compose run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js ;; @@ -149,6 +153,7 @@ case "$CMD" in --config dev-tools/.stylelintrc.js ;; formatters) + runweb pylint bookwyrm/ docker-compose run --rm dev-tools black celerywyrm bookwyrm docker-compose run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js docker-compose run --rm dev-tools npx stylelint \ diff --git a/requirements.dev.txt b/requirements.dev.txt new file mode 100644 index 000000000..d731ca92e --- /dev/null +++ b/requirements.dev.txt @@ -0,0 +1,7 @@ +pytest-django==4.1.0 +pytest==6.1.2 +pytest-cov==2.10.1 +pytest-env==0.6.2 +pytest-xdist==2.3.0 +pytidylib==0.3.2 +pylint==2.14.0 diff --git a/requirements.txt b/requirements.txt index 7614dc421..f1ece86db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,11 +26,3 @@ opentelemetry-sdk==1.8.0 opentelemetry-exporter-otlp-proto-grpc==1.8.0 opentelemetry-instrumentation-django==0.27b0 opentelemetry-instrumentation-celery==0.27b0 - -# Dev -pytest-django==4.1.0 -pytest==6.1.2 -pytest-cov==2.10.1 -pytest-env==0.6.2 -pytest-xdist==2.3.0 -pytidylib==0.3.2 From 6584cb640453c8de5a6849e19e25756c263dcd73 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Sun, 5 Jun 2022 14:56:47 -0700 Subject: [PATCH 031/167] Go back to one requirements.txt, simplify workflow The workflow can now use .pylintrc and the pylint req in requirements.txt rather than having the options inline and installing it separately --- .github/workflows/pylint.yml | 3 +-- Dockerfile | 3 --- requirements.dev.txt | 7 ------- requirements.txt | 9 +++++++++ 4 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 requirements.dev.txt diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 08661e9c2..a3117f7cb 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -21,8 +21,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install pylint - name: Analysing the code with pylint run: | - pylint bookwyrm/ --ignore=migrations --disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406,R0401,R0801 + pylint bookwyrm/ diff --git a/Dockerfile b/Dockerfile index 99a25768b..b3cd26e88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,3 @@ RUN apt-get update && apt-get install -y gettext libgettextpo-dev tidy && apt-ge COPY requirements.txt /app/ RUN pip install -r requirements.txt --no-cache-dir - -COPY requirements.dev.txt /app/ -RUN pip install -r requirements.dev.txt --no-cache-dir diff --git a/requirements.dev.txt b/requirements.dev.txt deleted file mode 100644 index d731ca92e..000000000 --- a/requirements.dev.txt +++ /dev/null @@ -1,7 +0,0 @@ -pytest-django==4.1.0 -pytest==6.1.2 -pytest-cov==2.10.1 -pytest-env==0.6.2 -pytest-xdist==2.3.0 -pytidylib==0.3.2 -pylint==2.14.0 diff --git a/requirements.txt b/requirements.txt index f1ece86db..96d98707c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,3 +26,12 @@ opentelemetry-sdk==1.8.0 opentelemetry-exporter-otlp-proto-grpc==1.8.0 opentelemetry-instrumentation-django==0.27b0 opentelemetry-instrumentation-celery==0.27b0 + +# Dev +pytest-django==4.1.0 +pytest==6.1.2 +pytest-cov==2.10.1 +pytest-env==0.6.2 +pytest-xdist==2.3.0 +pytidylib==0.3.2 +pylint==2.14.0 From 7f5d47a36f765d54ad47c8b272c5b778776e8f75 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Tue, 7 Jun 2022 23:14:45 -0700 Subject: [PATCH 032/167] Use values_list with flat, yay! --- .../management/commands/generate_preview_images.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bookwyrm/management/commands/generate_preview_images.py b/bookwyrm/management/commands/generate_preview_images.py index 7952803d8..9ff16c26a 100644 --- a/bookwyrm/management/commands/generate_preview_images.py +++ b/bookwyrm/management/commands/generate_preview_images.py @@ -56,12 +56,12 @@ class Command(BaseCommand): self.stdout.write(" OK 🖼") # Books - book_ids = [ - values["id"] - for values in models.Book.objects.select_subclasses() + book_ids = ( + models.Book.objects.select_subclasses() .filter() - .values("id") - ] + .values_list("id", flat=True) + ) + self.stdout.write( " → Book preview images ({}): ".format(len(book_ids)), ending="" ) From 1609b9b74cbec5a7fc82fae0a5ffcc791bf0b80e Mon Sep 17 00:00:00 2001 From: Jamie Slome Date: Thu, 30 Jun 2022 05:46:41 +0100 Subject: [PATCH 033/167] Create SECURITY.md --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..c4e5e9cf9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report security issues to `mousereeve@riseup.net` \ No newline at end of file From beb85ba94f25162634f784403fee05113f87d8bc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 30 Jun 2022 10:23:25 -0700 Subject: [PATCH 034/167] Updates locales --- locale/de_DE/LC_MESSAGES/django.mo | Bin 89936 -> 90852 bytes locale/de_DE/LC_MESSAGES/django.po | 182 +++++++++++++++++---------- locale/en_US/LC_MESSAGES/django.po | 10 +- locale/es_ES/LC_MESSAGES/django.mo | Bin 93859 -> 93859 bytes locale/es_ES/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/fi_FI/LC_MESSAGES/django.mo | Bin 92620 -> 93569 bytes locale/fi_FI/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/fr_FR/LC_MESSAGES/django.mo | Bin 96386 -> 97363 bytes locale/fr_FR/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/gl_ES/LC_MESSAGES/django.mo | Bin 91831 -> 92700 bytes locale/gl_ES/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/it_IT/LC_MESSAGES/django.mo | Bin 93253 -> 93253 bytes locale/it_IT/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/lt_LT/LC_MESSAGES/django.mo | Bin 95566 -> 95566 bytes locale/lt_LT/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/no_NO/LC_MESSAGES/django.mo | Bin 79314 -> 79314 bytes locale/no_NO/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/pt_BR/LC_MESSAGES/django.mo | Bin 92485 -> 92485 bytes locale/pt_BR/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/pt_PT/LC_MESSAGES/django.mo | Bin 86645 -> 86645 bytes locale/pt_PT/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/ro_RO/LC_MESSAGES/django.mo | Bin 94710 -> 94710 bytes locale/ro_RO/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/sv_SE/LC_MESSAGES/django.mo | Bin 92432 -> 92432 bytes locale/sv_SE/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/zh_Hans/LC_MESSAGES/django.mo | Bin 86950 -> 86950 bytes locale/zh_Hans/LC_MESSAGES/django.po | 140 ++++++++++++++------- locale/zh_Hant/LC_MESSAGES/django.mo | Bin 36001 -> 36001 bytes locale/zh_Hant/LC_MESSAGES/django.po | 140 ++++++++++++++------- 29 files changed, 1358 insertions(+), 654 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index ccd061ca53329dcc362b7a17be946653965e94af..049645c449cbb7c047c6e6909a3706b30f99b717 100644 GIT binary patch delta 23880 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 delta 23101 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 f!~CvsK1u82T)opIg;#Wi1%BQ\n" "Language-Team: German\n" "Language: de\n" @@ -46,6 +46,10 @@ msgstr "Unbegrenzt" msgid "Reading finish date cannot be before start date." msgstr "Enddatum darf nicht vor dem Startdatum liegen." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Ein Benutzer mit diesem Benutzernamen existiert bereits" @@ -70,8 +74,8 @@ msgstr "Reihenfolge der Liste" msgid "Book Title" msgstr "Buchtitel" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Bewertung" @@ -238,7 +242,7 @@ msgstr "Käuflich erhältlich" #: bookwyrm/models/link.py:53 msgid "Available for loan" -msgstr "Zum Liehen erhältlich" +msgstr "Zum Ausleihen erhältlich" #: bookwyrm/models/link.py:70 #: bookwyrm/templates/settings/link_domains/link_domains.html:23 @@ -247,7 +251,7 @@ msgstr "Bestätigt" #: bookwyrm/models/user.py:32 bookwyrm/templates/book/book.html:289 msgid "Reviews" -msgstr "Besprechungen" +msgstr "Rezensionen" #: bookwyrm/models/user.py:33 msgid "Comments" @@ -396,7 +400,7 @@ msgstr "Verfolge deine Lektüre, sprich über Bücher, schreibe Besprechungen un #: bookwyrm/templates/about/about.html:98 msgid "Meet your admins" -msgstr "Lerne deinen Admins kennen" +msgstr "Lerne deine Admins kennen" #: bookwyrm/templates/about/about.html:101 #, python-format @@ -426,7 +430,7 @@ msgstr "Verhaltenskodex" #: bookwyrm/templates/about/layout.html:11 msgid "Active users:" -msgstr "Aktive Benutzer*innen:" +msgstr "Aktive Nutzer*innen:" #: bookwyrm/templates/about/layout.html:15 msgid "Statuses posted:" @@ -806,7 +810,7 @@ msgstr "Fehler beim Laden des Titelbilds" #: bookwyrm/templates/book/book.html:108 msgid "Click to enlarge" -msgstr "Zum vergrößern anklicken" +msgstr "Zum Vergrößern anklicken" #: bookwyrm/templates/book/book.html:179 #, python-format @@ -829,7 +833,7 @@ msgstr "Beschreibung:" #, python-format msgid "%(count)s edition" msgid_plural "%(count)s editions" -msgstr[0] "" +msgstr[0] "%(count)s Auflage" msgstr[1] "%(count)s Auflagen" #: bookwyrm/templates/book/book.html:228 @@ -855,7 +859,7 @@ msgstr "Du hast keine Leseaktivität für dieses Buch." #: bookwyrm/templates/book/book.html:294 msgid "Your reviews" -msgstr "Deine Besprechungen" +msgstr "Deine Rezensionen" #: bookwyrm/templates/book/book.html:300 msgid "Your comments" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Weitere*n Autor*in hinzufügen" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Titelbild" @@ -1234,7 +1238,7 @@ msgstr "Datei-Links" #: bookwyrm/templates/book/file_links/links.html:9 msgid "Get a copy" -msgstr "Kopie erhalten" +msgstr "Exemplar erhalten" #: bookwyrm/templates/book/file_links/links.html:47 msgid "No links available" @@ -1709,25 +1713,30 @@ msgstr "Zu deinen Büchern hinzufügen" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Zu lesen" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" -msgstr "Aktuell lesend" +msgstr "Liest gerade" #: bookwyrm/templates/get_started/book_preview.html:12 #: bookwyrm/templates/shelf/shelf.html:88 #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Gelesen" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Was liest du gerade?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Zeile" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Titel" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Openlibrary-Schlüssel" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor*in" @@ -2947,7 +2956,7 @@ msgstr "Follower*innen manuell bestätigen" #: bookwyrm/templates/preferences/edit_user.html:123 msgid "Hide followers and following on profile" -msgstr "" +msgstr "Folgende und Gefolgte im Profil ausblenden" #: bookwyrm/templates/preferences/edit_user.html:128 msgid "Default post privacy:" @@ -2988,6 +2997,11 @@ msgstr "„%(book_title)s“ abschließen" msgid "Start \"%(book_title)s\"" msgstr "„%(book_title)s“ beginnen" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Lesedaten für „%(title)s“ aktualisieren" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Zu lesen angefangen" @@ -3020,7 +3035,7 @@ msgstr "Zu lesen angefangen" msgid "Progress" msgstr "Fortschritt" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Zwischenstände:" msgid "finished" msgstr "abgeschlossen" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Zeige alle Zwischenstände" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Diesen Zwischenstand löschen" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "angefangen" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Lesedaten bearbeiten" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Diese Lesedaten löschen" @@ -3289,7 +3308,7 @@ msgstr "Zeitplan löschen" #: bookwyrm/templates/settings/automod/rules.html:63 msgid "Run now" -msgstr "" +msgstr "Jetzt ausführen" #: bookwyrm/templates/settings/automod/rules.html:64 msgid "Last run date will not be updated" @@ -3298,11 +3317,11 @@ msgstr "" #: bookwyrm/templates/settings/automod/rules.html:69 #: bookwyrm/templates/settings/automod/rules.html:92 msgid "Schedule scan" -msgstr "" +msgstr "Scan planen" #: bookwyrm/templates/settings/automod/rules.html:101 msgid "Successfully added rule" -msgstr "" +msgstr "Regel erfolgreich hinzugefügt" #: bookwyrm/templates/settings/automod/rules.html:107 msgid "Add Rule" @@ -4034,7 +4053,7 @@ msgstr "Einladungsanfragen zulassen" #: bookwyrm/templates/settings/site.html:158 msgid "Set a question for invite requests" -msgstr "" +msgstr "Eine Frage für Einladungsanfragen festlegen" #: bookwyrm/templates/settings/site.html:163 msgid "Question:" @@ -4050,11 +4069,11 @@ msgstr "Hinweis für Einladungsanfragen:" #: bookwyrm/templates/settings/themes.html:10 msgid "Set instance default theme" -msgstr "" +msgstr "Instanz-Standard-Theme festlegen" #: bookwyrm/templates/settings/themes.html:19 msgid "Successfully added theme" -msgstr "" +msgstr "Theme erfolgreich hinzugefügt" #: bookwyrm/templates/settings/themes.html:26 msgid "How to add a theme" @@ -4263,11 +4282,11 @@ msgstr "" #: bookwyrm/templates/setup/admin.html:55 msgid "Learn more about moderation" -msgstr "" +msgstr "Mehr über Moderation erfahren" #: bookwyrm/templates/setup/config.html:5 msgid "Instance Configuration" -msgstr "" +msgstr "Instanzkonfiguration" #: bookwyrm/templates/setup/config.html:7 msgid "Make sure everything looks right before proceeding" @@ -4291,11 +4310,11 @@ msgstr "Einstellungen" #: bookwyrm/templates/setup/config.html:56 msgid "Instance domain:" -msgstr "" +msgstr "Instanz Domain:" #: bookwyrm/templates/setup/config.html:63 msgid "Protocol:" -msgstr "" +msgstr "Protokoll:" #: bookwyrm/templates/setup/config.html:81 msgid "Using S3:" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Benutzer*inprofil" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Alle Bücher" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s Buch" msgstr[1] "%(formatted_count)s Bücher" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(Anzeige: %(start)s&endash;%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Regal bearbeiten" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Regal löschen" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Ins Regal gestellt" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Gestartet" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Abgeschlossen" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "Bis" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Dieses Regal ist leer." @@ -4666,7 +4690,7 @@ msgstr "Ziel setzen" #: bookwyrm/templates/snippets/goal_progress.html:7 msgctxt "Goal successfully completed" msgid "Success!" -msgstr "" +msgstr "Erfolg!" #: bookwyrm/templates/snippets/goal_progress.html:9 #, python-format @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Optional)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Zwischenstand" @@ -4737,6 +4761,17 @@ msgstr "Zwischenstand" msgid "Start \"%(book_title)s\"" msgstr "„%(book_title)s“ beginnen" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Buch verschieben" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Zu lesen beginnen" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Auf Leseliste setzen" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Aus %(name)s entfernen" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Entfernen aus" @@ -4808,7 +4843,12 @@ msgstr "Entfernen aus" msgid "More shelves" msgstr "Mehr Regale" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Lesen abschließen" @@ -4903,6 +4943,16 @@ msgstr "hat %(book)s von %(book)s" msgstr "hat %(book)s besprochen" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s folgt niemandem" msgid "Edit profile" msgstr "Profil bearbeiten" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Alle %(size)s anzeigen" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Alle Bücher anzeigen" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Leseziel %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Benutzer*innenaktivität" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS-Feed" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Noch keine Aktivitäten!" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index 4b96725bf..2ea1905ca 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: 2022-05-31 23:50+0000\n" +"POT-Creation-Date: 2022-06-30 16:55+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -4870,11 +4870,15 @@ msgstr "" msgid "(%(percent)s%%)" msgstr "" -#: bookwyrm/templates/snippets/status/content_status.html:126 +#: bookwyrm/templates/snippets/status/content_status.html:116 +msgid "page" +msgstr "" + +#: bookwyrm/templates/snippets/status/content_status.html:129 msgid "Open image in new window" msgstr "" -#: bookwyrm/templates/snippets/status/content_status.html:145 +#: bookwyrm/templates/snippets/status/content_status.html:148 msgid "Hide status" msgstr "" diff --git a/locale/es_ES/LC_MESSAGES/django.mo b/locale/es_ES/LC_MESSAGES/django.mo index ac3c879c224b7d0ec19c665c5026d0f1457921b1..dc20de07a6bf4c16d18155a47658b91302090b0b 100644 GIT binary patch delta 25 hcmZ2{mv!-7)(y2cxy*D83>6FvtV~Tex8IbR3IK;$3C92c delta 25 hcmZ2{mv!-7)(y2cxlDD9OcV?ZtqjaIx8IbR3IK<63CI8d diff --git a/locale/es_ES/LC_MESSAGES/django.po b/locale/es_ES/LC_MESSAGES/django.po index 92dc13654..dc8f4bb26 100644 --- a/locale/es_ES/LC_MESSAGES/django.po +++ b/locale/es_ES/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Spanish\n" "Language: es\n" @@ -46,6 +46,10 @@ msgstr "Sin límite" msgid "Reading finish date cannot be before start date." msgstr "La fecha final de lectura no puede ser anterior a la fecha de inicio." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Este nombre de usuario ya está en uso." @@ -70,8 +74,8 @@ msgstr "Orden de la lista" msgid "Book Title" msgstr "Título" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Valoración" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Añadir Otro Autor" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Portada" @@ -1709,13 +1713,13 @@ msgstr "Añadir a tus libros" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Para leer" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Leyendo actualmente" @@ -1724,10 +1728,15 @@ msgstr "Leyendo actualmente" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Leído" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "¿Qué estás leyendo?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Fila" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Título" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Clave de OpenLibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor/Autora" @@ -2988,6 +2997,11 @@ msgstr "Terminar \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Empezar \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Actualizar fechas de lectura de «%(title)s»" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Lectura se empezó" @@ -3020,7 +3035,7 @@ msgstr "Lectura se empezó" msgid "Progress" msgstr "Progreso" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Actualizaciones de progreso:" msgid "finished" msgstr "terminado" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Mostrar todas las actualizaciones" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Eliminar esta actualización de progreso" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "empezado" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Editar fechas de lectura" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Eliminar estas fechas de lectura" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Perfil de usuario" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Todos los libros" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s libro" msgstr[1] "%(formatted_count)s libros" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(mostrando %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Editar estantería" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Eliminar estantería" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Archivado" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Empezado" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Terminado" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Esta estantería está vacía." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Opcional)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Actualizar progreso" @@ -4737,6 +4761,17 @@ msgstr "Actualizar progreso" msgid "Start \"%(book_title)s\"" msgstr "Empezar \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Mover libro" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Empezar a leer" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Quiero leer" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Quitar de %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Eliminar de" @@ -4808,7 +4843,12 @@ msgstr "Eliminar de" msgid "More shelves" msgstr "Más estanterías" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Terminar de leer" @@ -4903,6 +4943,16 @@ msgstr "reseñó %(book)s de %(book)s" msgstr "reseñó a %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s no sigue a nadie" msgid "Edit profile" msgstr "Editar perfil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Ver los %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Ver todos los libros" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Objetivo de Lectura de %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Actividad del usuario" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Feed RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "¡Aún no actividades!" diff --git a/locale/fi_FI/LC_MESSAGES/django.mo b/locale/fi_FI/LC_MESSAGES/django.mo index a36c6c9337a59868d3f38cac2e617e96175c0262..4fdb39f56a7d5e04a20b6483aff0b4948632b982 100644 GIT binary patch delta 24205 zcmZwP2YgTG!}swMBe6-0*dk^kA!5X=*cvg4+9O7YT17<7V^{4_v(&7;RjFOn-fD!Z zU0bPH^Z9&#*X6#wp65BQ`|A7J`>aaEw>97^su z6{;)Oabj9JPIhdI`Eeiy;{wc#M==*($J*$$a-1pglB3_P@h?yvO(%x~lpmzt;a2MtxeI6U(b1aBau_nJKs@+5k#Ko8w z4`6P*i`uCa9UUhd=0>HJrgRS7J%rhNIRF4cKji#zFV`mDfj|?$!LXY&;yI( zH>j;#ff{fcdsn*88GXo(r|3 zh0ss$e^DZuKxNbx*2k>a0yR)PX2yZY1$U;PJ}gNGmz>qAww%Uf||ges1C2AI=pMk|Fik2?03T#bqBIp15syO z#Fm#r?Oa9F!1b)HYUHadI?}PI9sLnC@H&jeqo{l2gpV{GRYYx36zYr{pe|(#OpaYq1NTDR z>S3tMw$1uGs{IL6`}3F=uc9WHWRz*20aY&mT@@52qJc`I&ax&de;8`ONvN66M{nGY zTKQg7M<-F2_yQ)wr>NKR6>8<_zBM}-fNB?lnt0i7*?&cEL`az@Ff1Q0Rmv7*pUj>ps*%j-d~pM{WHT)E)5p&fJ|$sB{o&f)!jMnt3f$!=~04)WqUYE9{H9 zd?Rf6EYwOCU#C-Iq4Qe~jrU5H*n^sE$gYCQuW# zqDH8lNkHB9K^TD3P!s+IHKE^8J9->-7p|ao_Bp1)q+>n(@ck#Efihzg48r_46t&_d zs2$pdI)Wpp`ZrM%eTBMY&Nx%g4^xs1L`^8frpse$($#JL7wCEaV~A*g1XPEkP-ip& zwRHVanuf+MXl%_=E7$-?Ki>vj+YbFz8Y%6^)W4eiCRc|R6hx*dSg-bW}vH;%^@Ox zLd|TA^=GU_dMj!|Nhg{!PlZYcT7ytK5Qb^6GHL>KQEy92)Xw!rO<*MIdop<ZxCo(eNAnOEF!+EH!Uv1rt>gYGr4xB_yXYXZOk^! z{4N-ao&_M|y3S!D+JQvW<-3g;@gbH+ujyuME237^00Xflu0t2sVAu@P{t9Yhw@?dv zf;uW^rdfawYGS$3M?e2764AibQ4MR`bQ8=(x)o{%dZBh^1cu`@jKG7al{>S{Z$N2L zcc22QT{YAXp~k2!?}_@EG9FVfzO#aeI^Kw-aGwhBwargD+oUt0wk{WHCkmqg>Vj~eg+YN9EBFlIql9pxjU9SB7YPy%%XpP`PX0jh%-)U6$ax@5ypD_o44 z$S;@$523dHDr&3$!B9*$$1J1*>O)q24*Rc;+mj)Opw4zK`r~d?#}};kQ3Jn6ywW~SL^j8m6-pnPU3hl5c9z%8f7PZw$=9`~-KB)IQ zz#4|SGm)r{zrYgM3?p$oYJlUY37$tS zgT-;UE#HLdU=M17r%)YVv*mZKFHlF6^e59#F4P2z*mO9$%7`SQj%wNpO>DX~>S(&7 zRzBROC))I4)I`>y&UP0j$D^ozPa|jSB%(fSX_lD3zN>=zPIO(u{%e5YWaPq`sDXY# z?Z6(?08dd9OtRFh)DN}A*-@7^9|qxPm>J_xM>H7K|7a|Tb5WOdA8MS-OWA)7aF-1E z3iG1RGBZ#RYM|n%6_!J-u%=DdL2uH{ZMrQ^Al)59@E!VK@N#1~>a8k=NwKa=q%e^N zw!#3cKzcYP!`-L`zoQ0DM9usPYC`u>cjOhOMDG=5LK#py=8t*{3Sj`2wdv-l_HI`q z+M<4_jwhf#B(rUWith7qA%H7%!z4NnJo`Sooxx!O6uDD)~EqG+58054vs?InYE~$x{8{>->BF75o#Q- z)n=#sJaYayi3Ctk5L01IOpOgtJJTBTV{g<7XQDdZiD_{^YC?Zt3cP{Z@&~9Rd5?Mx zQ>-!nG7^Y|NXMf7p2!(bgspIXMRoiqs^Lx4j31#o{D9gC-?e6E@}gd&3YZ5Qq888_ zwSd8x7RR9aor&pjKI+o0LsuD_iRj1e0n}@91=YZNomo*jR6T#xgbJZv*D|R3jWG=l zLe(2%oo(}1pmt_6YGJ!k6F9t%^H;_xGBn^NTk!_!HGF`YSi1G*y)B4(zbm2c#+Rse zUt=(SgIe(-RKM#{6WWHF;1SeBF4+8Q>)HQiWIQ254Qp>OXW0zZAP#-84{EEwMRo8a zYQUwaqdSe^_#8E0;f=g%SO!mFFPpCRv-waB#!&K?xkR+WbGG0S29VCW$xNgy>P%~) zwydGGIYyCgYh8s!NxwuLO~GIIJrJv*`k#x;&Dn&RFmAJXE8IauG}B4g91o*bRA39g zsbVeEYq=Gx;CWOB*?%;d1}cQ=ILxNYp;lNGbw@tOEZ77!PsJa95ta0sQO#+cRYwX$_YF8D?OZr zY4rX-C!&f;cA86hOKtvskM4iNZbc1n$fh4)X3}p^6Z73|etRy6T2OV=iW{Q( zX^npPHLCvb-R!^4VkQ~tXcg*`?6Dq4HN1$L-~-g{evVps#^212l|#>^Lk(CDwesdR zKL)drjzf(z3@75u-&}s7BvN>fnei^v)*eHh?Riv3w{7`DEKT|i*2nO@W-Eu|5Yj7A zTOG2`{Km5ggGnc1LrnHNA0upv(U{5I&$bY0i@9+(>O*n`E2G~5eh^_J48^6G2hU<& ze2)Fm|DgG`dkTh;-icc2Kd6NyKV*J*WkyZBJVv2Aj);!nJci(X)R!;oVY8J5P)8DG z(-klu>6+LJyP$6KU$(s55qtKi6*okEN0y@QP`0C{zrx4_U8f`wttbl9;8)lP`=U1< zMGbTYqp`*@^Ff-5dOOx(uLvQ%JFJ7rkDI^wXoyNLMD6fnOrrNc-wE^UbwO-L zK~wa@ZKw{9V|x4pQ{YW3g%7bK<~wPAKNy2)NUz1hxE<@_EsVmFr}&1Ti<-z@r5WGx zJ#EhVOVj`}ur|)e)c63k@>kaCXH5AN3?u(9)Q+Y9!`K0}^}k{nOncTWs0Id*ZiZ>G zKf1~oO++hQj+($))D~{B`Ma?Q>HXLe|F!9Q=lIN$9)N0>?!5UK;*X)Ed!a7(eAH2X zK)r_E7aS)B11_-t8fYjPCGk6q#hs}9{D~$%1eM^z}={U|Heuf{g>x|;NpzKilpyh zTP%EqKh5A6Vo?d?s)RvylGh78eq||27NUi#j6r5|KtkQrthQhv9>Fg72z9xd-!lV0#QvnS-{&`6oQ6Fx|A9yx1s(q}TYLhul753DG1Fu7tJQ2QP5Kb(Xq+czhuUF%lEbkt z{(;Rf`d@QrmZ19k8>`_5WaUn^r!0=~oxw!3@H<5N`nHR?!GyfPgX zL3L0bwRP1|xBd%My989bLDsRDkMu0m&g{Svcoc)t`Ohq*h)YDTQ7g=g1F$sC#Z~wR z>h&A?+I$C=;a8+@qK>TI8?!@AP-op0mERY&p(H38ob<`5Tkn4p zB6G<|Fd3Y;muDp`%&!^QFrPZ zdj9?Ig(t#A@-htqQJ1SQYGvgxGuFU1*b-adcAK9yiI+2vbWzk@IF34sv#14JwfX;{ zKWQham**~J#Z)foKt(VVbr;H@wy-g3#$TbfvKQ9CVOSFnq231HWM&7dqApuw)B<8r zJJlDp6GLoz6ngFix@s_&h-SVDb;~!RCbYw*5289cZM}p#%bS=3-&p;Vn~9V_<<~$> zyd84ZPA^=KlTqVT_4aZ-Gp*xoX4nQ*5Q~~&57gNXLVepOq0a6(>h(Q6H2QSROZHFh0fhm^+18$uQK>EI>_oIja3e z)PM(2TYlP>UqJ2fb=1P{qQ-gY64BNs zuZHS44mE)RHa#9Sz1S4>dfk*8pNWu zx)18CCtyWfgPPC-)Q9Q=>S!{jH~B%RqpN_*Z;IKlE4nHeMI-9_L8LWj-cO(*3zb2~V`WS?5Z2CLYQO-myWC?2E4YvHSFYmv8>?V?-4&PuwOyXxc z3PR1iA!;HWP-oa3HSr;s9p|C8ek-bgTFUB!I}js17n_ zG93h==k-I~f$FFUv_ws)BWgu`QAai$wX#X5GhT-JS+X6qGZ#@ubQiT_Z&4F(( zmIhTZC#vHjs1-(_Ce|1=fv%_tBw!?dYx57HIy{ZK1Bs}uzl-JYCF(5-&tm#3hfLgc z>J!mx)e3cKhGJQfwPt%0>j zM|;Y7|E3Yq7XN4~Y{I0Zx1ma6C&lo{2oJn9a7j+#Ih z)IxgVY3zro_5Md^GYy)e2Iz=-y?Ue0Y&>ef`KT3dM%|5*sH3=L(=SjvmO8s>mlt)( zN}}4;KpjmR)P#GWtF7xtL>-Pm&2$!O1@ll_y&844hcO&aVF)J6VFoCUYF`!AzA0+r zt!;Tv)Lj~m8hD{CUzLORUmfovLtC>SHRI#9!d295eu_cplhX`T9F<=K8)I`UgzHhS zVfiNAw!oY9<|~@sEN%+ZQTMqg2p?xrw?X z?@%jC6=>S!#A>7~p;kTuRXzoEc^9LOW*w^iFQ_}^?j@p`UBqJe52~X)`OIbNfTcY>hlJZgt#Aa~DoR+xyh2{p6bsFfZ= z&G2vQJM2O_QvuV#5LCUXs1>h5y$xG!`Uq;piKv~pg8E_i1U0d=1@%*u_b(?AoqYvV zh3cr+s4c4FzNiKxQ7iu*OW|_V%C4a5Qj9NJ%9gy zpNKBiD{Ice<~@zX>g3l)?aXx4mM=n0Xa{QGqZoo0u`>DunLj6dj#|(p)F*fqs{U=% zQ9MUiTl|5D&NfT187L4{u^1}9qRsytwNs685Vo=9m#ueg`E%?{`FqsBaYf94i%>_h z8a1(vMR@N}E%`VHwC z>J#i0YK|ly>If^N#%mnvnoAZ(hTc;bHM3Euh6_<2jD4sxynz}hZBa8pf7JIQ0JV^k zSOTL^{R~D;cs8otPpG3@i)y#sC8CBW(R15TU$S?oh6Re5fx=MfvZ(siP)F0;+7Y#5 zy{rRJ1B^g@S7xGK(`~4oJBMoT-Xx+KJw|o#4mFT>nAu8SRDL#8ejsWkp*BAPJ?}Z{ zb*zVNFb=h&2T=o^z;L{T8ZTXOFa4FT>*OG!Gpvv5CfJ`&mB$!?KBdeVS3)hM9csr0TE}Am=^s(;ccFInAiAE8iKxMC)R*ZM z>OIX++Po%Na4G4+r~yx+b|giFF+FNUSx{RagdtcIwV)PQ9y_5Xun6_~t%~6NSB0Hq zsDs1S%c!$@jB4PNF&(Ew-QIMl%a{}MVW#DM8K^t9#d@F&@4qt6 zk)f5}vIXx@4bzl09}<7mU5G%fyc%jEwNX3O4BKHF)OTYKYC<kK2J0jHy8xE!^jU8n&rp|<=r>izcm%v{!#sGZA>noxe!UHmdu5RHFA{uZOY9jMdN3j`;;xW`^dy9IHQ&sVDe#IJC1)Zv9 zqE%71Jsvf{EG&R4Q2m}n?dWaP4!x;rfB*NXW+sph_4;JS!We=2qQ#(I&;D2+r`Y@( zxRCTa)ayCFy4mX07)g3F*1%V&ek;}R^86c6ThvaTtl^ptuacn|7q4log1Sr%QCr#+ zwZ*MbXW0o=zb9&C!|1zu5RtJ9%o zm=kq0AvV7R>Jn8(-R`!iof(Ka%I{H^c{PUOZqyxlgzEo4oA$14`gMJYXeC)O0E1AM zCJIYnOH{*2*14$qEAS?6v+4QKUY>tuTaVfy|2pOlGELU1uzj05ayG z2HuVO_4zbv2OeVxI(5y!p{NOchCQ%0>T+&FUDiXWBY1^+Eq&^l38Y8m=R@sSIC}p6 zFN#Pc88N5{EI?hlji{L)L%j{xP%D3l>L^8hlkaa0MYXGnx)ZHXmo6UFZaS);rKk_w z4)px}eAR@ruo90VFc>ZMWI&G5Oo(?pw6@%Y9-xJmuVz!#mP7mqZ^nzaSL@M z?@QBV>a;a8|L+J)osK90tIjm&R8Nxt;rpJn*8Vib|K;7eH;to6;%J;t;}Ck_@R!jGY-Ufmq<+_Pf!DtZEbd< z7S<-+7GTTTuf(LmjCTVmx1UK43bM)M9{p8s*lM${jxGsK#Ia;b|gNpHZ$n7*U=Q*KAp881V$7(= z9fYDTS6K|e81%wbgs&B`&vN1$iBBK|>ZchG_uBIez+VY&VG0V`OqKjj$YLvNSG*|e zn#BCG{75aA=N91?^0dvxY~Ca4{YAPKZOfomT7fW!{4CTdW$VqQ-3Ib@QN{&zoj?-* zkoX%@5cHIx(tF!L=`Q*Y&kM>A+x(5htK0Zm+pZh!K0f;>E5c-aD0@MEf-R_F+f<~i zK{D+>Pkq8*!c)R3+gTXiC7idN9zh+?En7a3j^5g`MZ^o(j^B~jhI*5!mzMY+_>j=m7cUcKKhtgv>0gQa+2iYK z+vsOV7s|7dU)APKBfXrso1Mrx8m6|5=2KbEEAr0ZG%9&hR)KnY#$lp~IZ+fc?s0>mz`WH^7N`cBD5y2p3PSsJ!c6k$zq!ID&2)XU#+7O>)%O6ueE34{7*-hG|BRvIcl2?P!pZv1~{RVvj?^B*E4gb*- zK*q0APc_cy4ki{u?ny##x-Mb6SFH|&H8%YPT?QzVX99WSsb7>Zi+D{!Ao)k>Ya)4i zwqqsKCn?0{C83=E^E|`J3rpttdCgB|vTl-*l8!#u3Y~EI)Z)<@U6))v)tEwpjlU)R z1AXyh!P#NE|Aq82@~0AliBBSQAm~|5ox!x-W0KAS@<)@-hj(qCDr!x79pO*%zA*W& z)0f8UNc?CAN{Rice9U$xYST#177Vu?&a-*S=Z_2yzg{>h8jQ;b_egwY>+o~T`Oe1m zb-qm)PPu;)-q#eYdqB}!@rr~( zq#uiM;A3h8c?>4(<;JhtvTGTgTOXCN6r5*AZAGc!Djdj2JEtc@$3 zoMaogD{Fli|`qa#>I42U3E#<#>4o6{MuL@Kcl=M@&EhLFFkrn z+A<$@XdUT%I)6P|X&6f3*VqF8!J_03CBEJ^I%ge^QIua*L;L*6Wc2LA4V3>$JTGA; z@#Tbv#OD%9>H?D1(+59}?<^#-gz%5;=oABVrP3hsdXTr@)5QEI>nCwVe<9SOzMeva zF9}s?liv2F{Py|}PYwF3fiEfhPvi5OnA4qbl@2Q58!G5|XFF7U4|z{0t4O>c`74MY zu=P@sUPZh)Wk<0DD@-6SzrBRv_>6RN+UU7NoyuxMIKiJ;Jb$KdO+iyK^vuDsR1Q_z zcG8>pJ@RUi#jk$<^X#?pRMdM)ygZ!`x20EbI_Xs8XR`hHs861SSU`Cn_kX(WXg2;v zVK`={v7Q{Zu}PW#&bJ*cpiZ!DJD>PZw$c_nLViKoo+ZCF&LnTCt*dJDiMs=AN2_rk z6{ll<3QiL*jtvOaiJ!6cnh~E%p1*qd?QeGsT@LRPS77pqsePRygKDONq=JpN<;d4`bs3|*-rR@ z@C)gj%Ha8rc9~3+|FZu>p)M8TDA2PJe;~by@Phbvc#8qo~?(6(NCz6Cp`3UK$5JKfe&pTe_$l(hQyQF0XEsPG~|yVOd&nh z<{cnilz0`r|J_MMkr;xR7^I1(ODfRO1kz>5?`Rv^A}606WGorUDZfp<>BJjj<&TxD ze&p#{N+0pm%})HEkNxTVcMuAzp{*Ei3n$`2%Jkf#;b(TxC* zZM*^L%!J$I6{7tR^4k-7kbXpPf1@yvjJ3AGf7TD!*v6@%zXI?)f8hh0zlogsbovu{ zKharU;$D=MC;b~vwQaWHBhsg-bDDTw!aUm6;qRS6aS9F_yq7m>e!_(-fpm_}UB7UIol`|-*6F@l9Zi91s(M*FxusqIbf5_S>E6R`2_YIr(jDjoVWgrBRA57pe zcd!+idL9rC(jXTDk019=)zuC59$UA529VGvl zC(iiUiOiv}nQHR{kv@b`ga*Vn5gHNqrcOKJk8v%2d}=a4IwtImrOAxIGNfk^_oePN z(m}-Y6Sfk{k*6mKb@aa*bBd9XoQ#finv`@jp|b`dFC+1CR9tBXEKOX`81nU`u_~UH zI_F7WP=co}eGDZ0W!qk)tQYyKJ*E5+3*E}LL*<>N!l6$(97V&?gmRR1r=vHvqbjs{ zPQ3{7l3)hg$5YacNDrZY9qQ&Gt!L6Fefp4BpLDz_a-G6d>}M-Pd@`AE@|)WZyoqlh z?4e$Lo7a~Pz9r-!9Y*ja-k6YqI_2r-3H4_a^qj;(QFZWZ4MH?Cch!|{`S;hL0E_U z%Y?~Wy#0Z;ONJn4LD3bID@|%!;N&ExOBYlxjnox@HjJ)>LO-J~GI-il(grKK5 zd1r_RF`;Xux07y3(36I+i?(_~^)q;~El@@=TM&f*(!sx&gOJyDtU4uaohsy|B8;=` zbKz9N302}bZtH!6bIIR~n@y2(kMuCo8W zLxP?uNjFY!QK(khwjDZm?-bBGzQ@;J$99-HW>JBSI~EO3UAV{B0S#hJSzv*}?Rxa+ z(k8xheAn2Z-hur8C;s2ksjb)K3MSdhRQ8n7(Z|OBleXm>E3W+^b+Yd9ox5&4xAk() zG-g=GGyK${$HS6)VjI6WACe?h>Cmv^0bym!g_YX)ZKC^SirTTgyTta3?>FOUQLoU= z-o?E7ruDUXdlv`9$M)#bJGT3b$dX=J@^tOfCAM4V?y=pS|EEI0^&xYo#;o!G90UG; z_5Po{_|CQ--GA)w)4a_CD|jtVoxEY&wq3ex&RxqZYk*%DGu7Dm_-y; z+{TWR8s}jcZpZ9+1yf>zCXSO1Q)6W;gr#v57Q^2#7ba-xIQ1|eHpdBg*l}FW6CzK@ z*x1Z*(%@W5^Wt{YKo2nx{aZK=b91s`KCFV#I1FpxuNaB`EgdHVmO)=^jX~HOLvSKi z!JpjuF30(#h==1OZ{;`v6l81dIJ>a~s^LGF4t?7=P94mNS#Sg@e;umbZ>R}g$Bg(5 z(__ZAW~ZVt73q35-2OgA8dw+u!}A4(}Vq2#$cN<61AcUs0IsB zPw4|ODm&>!!k2L6aiFlkQ$2BF%8VPedQzE}{GVFj11P!H8Xb5zCN)}g2l z$D$@Q1J&_T^uvwTgQ#|AP#s^vaD0TCfL|}i@y1lBBhHMf?{e9K@tB;9*{B96EiZ$*BlU1OPQnn(%}p$THBgs$EUMqXF#unqb~0f1QksP}k2Y6AOF4PT;m;6Ky~J^Qn3m<%vQkybX{9o4}gn;wUn z;7rs4mY~{iLcQd5Q9IZG)vgU{;yuT(|B4JILuWnO7EH4h=iB@> z)~(h9*5jxSFQ6uR+vdMQ4frqW?MgJ(>{uvzl5UKu-*PPbue0t+hIU{WYUR^0AuhqR zxEgh)M=%htqmJmU^$Thtp5x4p_@cHx2z3VvqwY=>n{J7kU>_F|&14uR!fDpIsEI8_ zt#C7{gZ;Mr9BL(3&Q5|(g zO~8d((InK)Y(m}k9TgPYyjwYO7?m`f1XLF(^P!#FM<&-C)fvRGCY>8pG z2esmxs2zHXI)eBUP5rc}iAJI>Ss_%t7)*?fP!non)4kD~^iZ2W9^LQ%Tq0_?3Dx02 z)S1PiZu1q?if*C?dWf3vCrpAqlgvtkQ7g=bT0lY61e#!e>}<=IqK zh`fQC*#qk{tVsF|YC=V)m@_YpN;k5$M4fd9Oo{{12gjh^mRYEs+kl$D0o3>8_bHse zw*J1&c#oP$@~P%1Qe!OXP*lUmsPgydi(gS6nqZT)@gOH@anP&?o?-Au$6wZ$1wcPKw*!eXc+YJob6ai|3> zKpnwK7ZDA#&bkXVz%f+Ci>Q^}KuzR1>eBs#+L3rO%!-qt>V=?Q(@0ePTBsvwg4M7i z>b>8MIs(^aA{y`=s>Ap*%})5Db|wUqV*%8bRz%IbIjVjeo9=-cs4s5D5tttH&N6>5 zP!sjL;39M{02$Zi#G7q)AUW#tWxy1e8H-|J48Xpq6-~fUoP|H*F5HA2el+ca=9r14 zLoF;D>Zl5#7Els3v3i(@@twXzH1JT=ibmS>RMfz;Q9H06{cu0##Zy=iow;V^g)kS% za;Q7d2i0x}>W9!2)RwP9{Y*KAUX1VDC8Ca>VibN+0p^`&@{6LuTl zhoUAt4Ljm0oA#Y=1`I+ZFM;2#PXD6Ut6RGtY~uF&ee?jZt@?H)V;yY0QcbF$elBGXoYwEu=hZXDVA8Aa9Y&X-h;~I~O&hji{OLu<3)= zSk(J`8nqKQFf%^4)<@=!)7=&6#1}w_>PA($aqE4tS>W+~( z1a&kUZT>z~!{exl{e|lAp)G%D{en80#4AnvOsEOuvFSoKT^?QPsH)9qib}UZ9Z4V5 zipSgZY@1$>n#fMngpZ+i;5=%e%gEU}w@@E6|5fI%@hYOe54}+Rk6*?9rz5hM3=Om& zwesVr0Y0H77gFz!c1aD^Qp81ZtdnsQzEBX8#rW zN=8QXSz`vujT)#RYK770iB)a7HYOz9!lv8f6w-Y#0^_eW{X|*|q28uwjE{9ND>iTu zNkn8g7Q^wF0Ao=N{y+_U3pMlms0qDB-HorP6(?P1CKQO;v2>{0pA$o{q)oR#weN-6 zA(xAYI-Z63aH*|u5w$aS(EVjYP3SACzW;hN(e#*^bS6~&N~i@jKn>Iawc@VW6?jyRgBqZ#%^!kUNl!xEnH{K|dVre1Gt_JS4jITv z^pn}CU~4Fb=>3l%l7tFX(Hk3}wx$h+;Xu?17o$2pirSHrs0m#~P5d!x%imyPOt8_s zhRLur>8u!zoiPW_#8AEehlr@-yQqdwP&0mq>d@+xl~EI}gX*}M zO}9n$(;Zc>KkDroh8k}<>UG?^nf=#$dw~qC>@ligf}hQg<)o;U6hsYF4t=pYY9h^1 z19Y+ZeX$|w(WrK}Fd05a)&GLp(ZpNK4yM_{{;Pw$WMs#psN2~N^#vP`8gM@r#*=ss z6K*x>%b1O{|2Fd*PBGL9JE8JNUoF24UlICe~*imFaW=xKPKO4CKiT`NH;?*Xb<+p>zEd+?J}3r)tQJo*o2zd5!7pR z8a2aBp$c_8I$mPPVVmKWvRUnyVO&cTn{bA2jV#ppGc5P3Oeqqzj-fVMSE` z_0gq_K}1sGc+||6V0zq+TG0j6itnI0dWO1eUs3gwA2LUf1=UXx)ZM6IZGvjo0d+)! zFddFO#QtmL%gE3c9!G8YCDed7P%D3A^Iu>p(jQO*`Tb)4mOKmoNO~t~!c~7YJJJ|+ zv~5xS^hK2q#sWD0SC{#h$G?!FtxSHHuM`$WZS`J^!aPUJ-Dr=sNzXv8f%5>X;PRuq zYWNbK>HUhImca4FWpyO>8}ZD2V0>R_QEK=|AUFNBV!Bd z=Y8-Qvx4H7m2?bN!`>K!hp`O$oHY}xiApa)o%KD`0GZF3zxl|8-lPX%6&z!|pmN4{ zLe87B?tyw{O$Du^e250L+~N`pw~r{4n*x-LDU3_qjs>o&98dcR@PopGbHxzSnXZ{zTNZU!I$#jaM7~KP!}{3f z2|@4wej+W%$oSN}wHF9XD?c+wuov5reu5pa=5w>fdoh^w100RtFc*$~VZQO( zu_fuJ7=l$_nlEQJ?63F#5Rrxy6ntea&2&_U=ddh3L9IOZYx7ogM6LWND*qvRV#YV- zmWN|1(vdbDgWjZTV+w4JzSvvkjPHyjk{Bmp68sT$S(c$DvLDsKCF>nbMEW^q$M+b3 zA#cr(*(lTi6>Pdb`jGBu^ZR2m(qqw;oXC$vE2dAR?{}q$s1?+{l-?9IiS?%{`z?P`n-V?PW<1sJJwCPw>{j-=5 zZ`$;I)RDYJO+4^}X`cnPbCIZ9Ukuf*C90neAJ~6I`jL?dN1?W6E#|{rs4aeqT1ntP z<~6E_8A-Rp0yqwT!b6w^yL>d?ftlEe^cmEV75QX#s5I)R>$`}kpcQK7olp}Rg#BrP^}pwfIig=t^)I6GUAKv(Ao2(` zfiIX6lm2Hu5TU4n3Zs6rDUFM;rA>cBtt9rpKnZ1&5#p%9X%Ov=C~7F{u0+s0lVg_16LU zwmXASM|T_bdcH^15BBtMA62NQhxzyaxyVpKA=FArqZ(GV=~lM9tF=FB%ZH;rD6_FB zF30S66I)~Agk~XKQAaZgHO?$l`^5=eX27jvXhjEXg(IjfK80G@MbtodQCs^GwbG9^ z?VZSU9Dsi0r$-H#+olVmE@ws50_$J~Z0;hGg^1Jut5E}QL!H@P)CA7i@>{5ZpP}x; zH=Cc#%j{ShYb5GO%h_~G)QbC|F8KuPfUXrpG}EN~`Xd8SGfj({P*&8Ph(fKroK085 z3Z$E%CcGN8wHs0OcA@(F1vBGu)Fpp`nz)n1y;J=AUm{vz2x?`yuql>8Ra}DFvQ4P> zdJk%1XHa+KI;#C^499P%fy2E$+@JK^sD5jsCeY5N2VgS&{GVtu=A+JTqq~4VDxn&j zLhZmUTmI7KJ4ww1{89D7QAbu7Rlf#mt6QMXdLS0Zd8i5fg(>y^KOv&CaePcc0P5_* zQTb&s71p=;Ju!szWYkVNg9Hlq*f zEJvbNG9A^?B3r%#^<(!a>e4+xy*Ln5;o<%`wy&T|{l!L)1X8P?zf;RJ}wgOviz!6^5cFRthzN`lt!C#Axhg z^S7b;a~&X}4v(U?{vsB^yQtSFU4ZE@Giv5VQNJlwMBSM#SO9yX240J5cMw%S7SrMd z)Z6e1by*Xqbhmdo0YtRIRMt?`r#Oc-4^|{y(3THFZSi%U8ZiRfhXJYIjD};qjqKss{S5Z z{s-zZ-^6VA1~t*NsZD+!tVg;WhU3E2y#IP1kCLGk+(LEu9JK@AP!kDGV>&2kt&F-e z%~31vfSTB7RJ%!d4p*TrYyY$!?!Sy)fOSZ}MvYTG9q+$Z-XNXH=#1)UC~D@TPz~mx z26}-ybMN%#yAX^=NEfw!L*0=h8O%h^pz1$D4fr1Qn^2+<5BIP0*BkWB28>)ThOs3uss0GhK-UgSm z%4Y0Dt@tQvCr+S#3SLKj={}-*XCIC#k3@ZVs-QY} zW!CG?`yWU|TTuvg#`RFQw>O61BGk9~AZo>bqAt}vYoaXXHO+zL$S;bjHypL)Q&1CH ziyC+rM&L0lrSH!hBIPlExLMI))F*fjs=;~GQQSst@e|b9dSo>N`Jn2hM&)O<`T0?A zNhutPF}D1;^&-0e`@h>nI#S^=YT(-0%z#r+M=}?+)r(PEy%%*vXHjQ+7d6m()DC>b zDp)qVxiiyI6I_V;pshzOXm57je|<=flA*IbiTVUTLmf%79OeuoPy?1i?LckRYuX7l zv7V@QlTqJ`&8Q*5dqqcM#YM{NC7h_Qa zenOpH!rZ2VK-Alk88tv@)K9l6sGV$zRdFC{VZWg!a1AxlzmeY`T+TBh8sIf*0$))B zc}AMEPl@U{JL+{RYSVR56K#iT-wV~=g&JrK>dQD4qwylRo(~H!7%Gg)KRTQ)!&Kg_z>#S9z|Ww^B9IVQ0?Ot zF#V-0!22IUMn*DJu{0`O6?IFyS%+FDp;o@YrnjNm9Y%dWPND9?bJSh8}*v}hdPSDLgtQypjKP}b6`muqnumx`d@M1RG#94#bkU7uDfsR7YM#%z$Z717<`W zSp@3HN}#@oF&Kj#QLp26)Ma!XC!)*s)D}2J&CCK&6~nBBPy<#$O|Us?MSW2NOh;|` zo%7wWPeLhamH)P%00?#KgVqAuqt5q;_Y!*C2PW>yr9T1k0p1JndMp(ZvIHQ;pA zfOAntvJ^GYI-A~sn!rKS9XXC6_z2VL{ZCxnyr)^L#ZevC!ANY3x{Q-hXSTq)0k!4( zPy@%J&i)Lx$4jUM6fa@k_v)yf?ugo%A268lovB1L;9ArNV>4=tV^JTX>!>sLE@@uR zRJez9T`Y~h(PpBxP?vZlYJjzv8TX+2y@lGj52zhVQi}Iq0|ye3=}@ml7-q%ts4rD_ z)N3~$Yv3}Q{|1+nPFmW$cAHUKy&t177RzIzGN#{Z*o|}#)K1CiCh8;fKwZ-Pm=n*S?#O?r50h6#lTL|R zK!}S-2$4Lf%Tf#TVH;F~xz<&v23zrOJYv&pD|xv8ZP^~w&SZ!&cPAU_tV>#JV-C{o zZF(k#kan#hqJfX2e&xD~TKPxRhsmq588`|xq4L-rYom7R2vso zu}*b!7oMYzBw-D+AU{-pVW=IBz$m@{#fa3wUZ^wr4JYGU9EZbe+CSsf@^DI!u8uJ{ z1-IfAY>bm?d$|9t_9N6Mxo#cv{`W!EpO4k?J{H8Ny1f57!>&a1Cz`=H5SO4n9I5IV zOQLRdThtK@z)&2ERdGF5!jGtI@ho}LQH8OwUkQ#M#J#h#Q!3y}P5%0eS zDAm~9<{DU;bTibMuScEP7HolgP)C)ziHG~Y=jo1xNgqZH_ywcTtEri23DgH{1*)HQ zsLQ?u)&CI}5uND?)XEb#Gb`$k+Pbl*0T!Spb_uoB8Jn9GbVf~R8gB;8x~eozz3+@5Oo;)S5r7VmH(o|BQOgPM`*Q zhWdVdMy)uwjd_dGqqaUA^)}?id{_)y>HY6PM7Qw*Zbt96W(W3RH`0G#Ni5RNqz9qC z<&RO9^f?a16z$CblTrQ6!FG5C2V;Q_rr)jTJ~Hf}_x}qK_wDXz&Ts(g5{<$T+<+c< zhEb!4tS5erI4_C&*$|J95@D20*CzgkaD(uIFp;{&P_Jk?&75a4A&C0vxqnV33iXV$ zKBSTd`2}sdJ7o)OLyk}XHIDx6i8GJ9UWE44i?1J-JXZ;$DLY4qd+yoz2I{7x?kB<~ z^0L!L-yi-(B7@lh5>l{+_(}2(5$Y23u!{~m?er%6OWp-SQbJzRdR7s7*gi72bId<< zboxoj{dO`^e>*Pwf8{Qxux;c=!7$>wL?5WArxzh7v-}ZzP_E~!t=}7W*}Pctca#1D zeW`yGhmhu_;9uMF;iA77+m0glXL>m4vI$uKpWhW!CVq#IO||SZnGVX5SAb5^5>Lqh z|M&Ts@sMfbB%NLS<1M~5`7Y-O8KViE z36pH)+1Skvn2`L3gpV{TiNh!hqO+uwpC@k>>GrnnEYe%3a~l67e>owV@RGdkgk9wC z!M>=EmV5vCqB?~MdU6r=xMSuY!>G)!2fUB`*^qc@LI(yLf=lpk@=MybYLWW8cy-Ey z2&u?BY4cx_EZ_){}y^^QoVae%IMLri5SND059AwTuekHun!QJ5#ZiP46VV)y8L&A5O?h-c&;5 zcN3Xs<6G?@#jNh%87bRt)B0f*_wWl7|NSQ&oh8IQIjH!K#9iCqGx1Q$yQp5|5wrhn3eP*+=`8cSJE~7yPYT?ReK4iXbN>isauezBA9pSDkJ6-nAR3H%2C5Bl{U}dn`wgbu1RHmq zrNSM;PIqlICyb+>d@}JvLG2AM*1Mzd|@>+ite?@=!KWeaH1l zzCZPj*zz^;IDdY;>lXp1t{qUn^~61yDN}X^45E_(m>GAF_rg{>6Ic2FV=?MKqk{pm{X!^0(DQ_R{g&iSotXqZeQ~*oI<1J; zBtDifi1<%9i7=1Qi7OiNfn2q&Ei)6i%p zKBZx9!g1340_?0%PdvX8su6;zuV)>m#P)<&wA)AB6nF-6F|neQC&jpDbbQYL4TYts zr02AC26=ks6PA;=&ZZCJk9IJXAEYdkEn7*xFL^%ri2PUh25Z{-Q?b6SoBV$#!TE>L zs0@WysI24AlgJuqlI}m>C8tgqIv7G;COSw&JcM|x+7b>Ee^0xGgbAdFlh)J1{ZHzX zcbs@`+D<0En)XliD&-_|GL7<+*^+c0Li+!mA%D9;`3>^)oTpygQ;+)mDcu=M7)iXf zt+N)>Q?EJ|OA&uU_>cJSg!_c!l%*lGChq?JgwXgFl|~TsoT6|FK~ENIA?l1E6eldQ zd0!~sN}C#Zlf0s8z>~oCvj>xr&PkhXlxJa4{H40npZI5-rT1UYb1HoQj3?d2cJh7x z@8nMqMUYq4<`2hSgem;_)BT5t^8aVB6*fI8 zt^+C;XOJc2?Jp}hKcv4$eRnt(X4S7W|?m1^8Z7@CU^t7YSZQ^5G{No+rG8t=4 znft%n%x5e9O}?Jw3{uJFDP70LQxShboi?PW5wA>`PCChV6G&t09>Iq@gt-zQ{abqP^V zBI0^p8{GdqL|Ij0^)QkFmfEss^mUZ9o(S5NFj4dVouZ&JA&}64igzd+Ob4a02p+&& zaSd=2b;eWoKg>$n7rm+Xn!LE@I`Kk;%9OppQWR7ooF=WO7Iq=Ho|v@Ljl^9-Q_}y@ zpeNR*({;8y2YGtdSbxXogoZY4O8HSvo9XoP{S!vIzpWQ(cTMHp^!uNl+_phV8W$%t zCcS|MCyDF1XI1=!t^1I8G8_L)`54kouqvUnt?y0wX2Os3^_;u_1|Mh3TH*kmf0)hC zt9X!#&2T881M#P*$DcZX5D%pT{XeCaC9fapnS|ohn@af=jC%$Vc}e=Z&DdhgV!x}C zingOPXj(eVgL?YWQ9;si&qx{+CGQ)y#>CXSih6u(y~MWD0hC4CvKhoZDW6MOHuA1w zcPwX`I%z3yMB25Af2<`D_w1lz6nT3IkI5fT!EN#~VktWGB6Or|8hITFj-5ny^2}kH zo^p_XhV~c8-$=bLc8sB<_0%LUubONo@r=X)3bqkHK*b2sBZ&Wn}vDB+QEZt`+#_M%7>}gk<3&y?1Lpp-=)zf;t_Nmly}96O7LtWUH|(nQ|3t9AS)9I zCwM87yxvfe2Ahc|BflN#87lkkDM5aI!g=ZqWg@#N`-qvzJMmpTMOzYnqRjo@e<|Z4 zjr1hJZwzvP!q3D<5no9B1M10XO-y_V!I!fC$jePwKzs-0vvqQ)0Z&Kz(O=1xpj^)@ zgL6aYUzNfvgt%v$tyF_fB5g+}FadS^FbNeOQ0H&bT}jWeb=3YTaSxmBVf*Yw-4BFZ zw%^3;#zo?TDW9*O|9WbW_<(=8Qw%^Sp9t4Tx5XcAr@^*-An9zj!(V7ypL9!1OZh%R zEa}&z8xh}usTtId(1-je(%;DUB>q6-Zz04zg^2t>L9w_Dy!%~T(b9Bqig3(MU?25& zlh!kkyx&LU$g4*@?%79P z7n@j!yKKkh>G%)gscl+Snp3wD={dxYDTC)N>6Ny>pNJ38_>0M?L|96wLGYk6J)#<& z=ow7@1&k)MD|rn_7qRs+*gC4WoOl&1L+5pV;qrt-lBr^&}^w zFQGf>N%$L;`r6KKkUmVfMA=uuG2(hI66O;hVbcw%Ka27}()UqM7!E~Gn^xWm>eW;m z?SBSVvIesgekP=|6)T`0X+7s?PzKlAfgWR1!fKm7@m=R$#N*NDBHBdLW)PO7UUK3` ziT_Ld8g)X6SKCeGJ&_O^w6UFp;3X>e#GeTpiRZ-8*pQHpx+hW3SlXte!%vjYj<>B@ zlkke$cC8%gz3r!;=X!68*?%qVw&Pb$cqEC+nKyq(WS%0C1-31`=Bm4^Mjns;KD)Y= V^jP7&E4Z>pV92hgojrc^_#d;tvVQ;o diff --git a/locale/fi_FI/LC_MESSAGES/django.po b/locale/fi_FI/LC_MESSAGES/django.po index 0241e1e41..bb26b0a0b 100644 --- a/locale/fi_FI/LC_MESSAGES/django.po +++ b/locale/fi_FI/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 09:05\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Finnish\n" "Language: fi\n" @@ -46,6 +46,10 @@ msgstr "rajattomasti" msgid "Reading finish date cannot be before start date." msgstr "Lopetuspäivä ei voi olla ennen aloituspäivää." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "Keskeytyspäivä ei voi olla ennen aloituspäivää." + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Käyttäjänimi on jo varattu" @@ -70,8 +74,8 @@ msgstr "Lisäysjärjestys" msgid "Book Title" msgstr "Kirjan nimi" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Arvosana" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Yksi tekijä lisää" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Kansikuva" @@ -1709,13 +1713,13 @@ msgstr "Lisää omiin kirjoihin" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Lukujono" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Luettavana" @@ -1724,10 +1728,15 @@ msgstr "Luettavana" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Luettu" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "Keskeytti lukemisen" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Mitä luet?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Rivi" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Nimi" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Openlibrary-avain" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Tekijä" @@ -2988,6 +2997,11 @@ msgstr "Merkitse ”%(book_title)s” luetuksi" msgid "Start \"%(book_title)s\"" msgstr "Aloita ”%(book_title)s”" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Keskeytä teoksen ”%(book_title)s” lukeminen" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Päivitä teoksen %(title)s lukuajankohtaa" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Alkoi lukea" @@ -3020,7 +3035,7 @@ msgstr "Alkoi lukea" msgid "Progress" msgstr "Eteneminen" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Etenemispäivitykset:" msgid "finished" msgstr "luettu" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "keskeytetty" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Näytä kaikki päivitykset" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Poista etenemispäivitys" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "aloitettu" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Muokkaa lukuajankohtaa" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Poista lukuajankohta" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Käyttäjäprofiili" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Kaikki kirjat" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s kirja" msgstr[1] "%(formatted_count)s kirjaa" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(näytetään %(start)s–%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Muokkaa hyllyä" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Poista hylly" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Hyllytetty" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Aloitettu" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Lopetettu" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "Saakka" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Hylly on tyhjä." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(valinnainen)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Etenemispäivitys" @@ -4737,6 +4761,17 @@ msgstr "Etenemispäivitys" msgid "Start \"%(book_title)s\"" msgstr "Aloita %(book_title)s" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Keskeytä teoksen ”%(book_title)s” lukeminen" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "Keskeytti lukemisen" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Siirrä kirja" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Aloita lukeminen" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Lisää lukujonoon" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Poista hyllystä %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Poista hyllystä" @@ -4808,7 +4843,12 @@ msgstr "Poista hyllystä" msgid "More shelves" msgstr "Lisää hyllyjä" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "Keskeytä lukeminen" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Lopeta lukeminen" @@ -4903,6 +4943,16 @@ msgstr "kirjoitti arvion teoksesta %(author_name)s%(book)s" msgstr "kirjoitti arvion teoksesta %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "keskeytti teoksen %(author_name)s: %(book)s lukemisen" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "keskeytti teoksen %(book)s lukemisen" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s ei seuraa muita käyttäjiä" msgid "Edit profile" msgstr "Muokkaa profiilia" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Näytä kaikki %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Näytä kaikki kirjat" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Lukutavoite vuodelle %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Käyttäjän toiminta" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS-syöte" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Ei toimintaa!" diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 1414a05541850774156dd0c1b35482baaca20e5d..827080b0c093c10260aa2e1fdbd71ed2e4884906 100644 GIT binary patch delta 24228 zcmaLf1$0%{!mi=9kq{(6f_q3H2_ZlT4hilS2(HC~6nBbk+*;fV#jUs%hvKd+ULa_3 zD5W@s|NZuyoWp;|y?2c>d8V!DYwew+;|zO|@b|X~-8cLaOn10q5;#s~Tpi#z#}YbD zWCi6qPK&0FlM!2D4jhP~xDeCeNz8(`u^Kwf9H%T)$4H!rdGRFH#}D`o#x!@F{f^^y zHWGP6MsIR6VT%@y6M+L!9j(K(coi9&^8yQC>XwdE8Y^Qh9E;(26|-T|R*sVbb7MLz zf&N$rt79)uzT0v3DdKXRE0~&s7p)y<8+x@dH~xxQNMFLb_zHutYOKlcj=FCm2H+CR zjz=&nK18jQcU#BFfLT%LqS%!Foti{6(p6XxcVZI!%jSQ;oTQVsbDZRuAGK1Y@mp+) z!|@0PVzu^;(-pf~aZNcEsZ~+_WA}E!dI9J zb9ZC(SPzw6ia~e=6XI*@M@&UJUU#++)1o(KK_3jlL|D+4M|NlZl~K-SR6}3VF{m5b zpvrro8tRYnaX4yAMx!6DL3O+rli+zwhHheCdU-+9;QN8R0F}NiY2TS zPz^?-2GkhUaC=ONy{)5A_sv8#ybyzNJ!$}#F)7|ct@u+^eRrjvrl2 zqE@=U%^!zujcg(j?d2TQQY}O^uogArEvU0`5H-+?sD|&MI(~#2_y^PgyaqZ>am;`^ zY;{rht;I>W8`WRUL9D+D>JBm;v_=*5Mh#?uO^-o!Fu^(-b*Pr0R^|+9N$;U%_ymjK zM=Xj32b(k188xAwQ0=c8%=&A@+sM#NPM`*G4b|XnRD%y~`8%7R#J)FtQD-27H2}58 zxovqN)XGJnI*ztBv-us}L^4t^2sMyd)>Sx>^d8h!)Er_4QXkb}TU35m)J*!K208+H zK%8lq4igVGpN82{6DxzMuo7xO?j}TZ20Ea&qBm;9BTx;`u;q(wdL62PUDmUxy}pZi zG21Zn^wh*`q<5fJ@+xY;w@@8FMEY?%Z)}Cc!_CsAL>;b-s6Eey8c3*37eO^p)~0Kr zCeQ>mfp)0-`=Flp0k(V+>b|*{30GnoJ^zP^=*DZPkv_KRzfm2#MwkwgqZ-VJTIzhL z@=~aVtD}~@G3s&af!fmVQ7bwR)$w|a#gnLW>i$cZ9dDur7;luhKP9T3Ke|;ALPQ-EM(t%KRQ@njhm%kvUw~e? z3pMitsD{p>4)JA7fG<&xqzS)RD*L+16^VBx1r9&0o1_GpjPY=Cd9xorhcw5tiSfY7#UiD%BYz)LN9EGnXwCM zPrt{sxCFg%r}ZFeBBwABUP3K>9O?|X#+tK}8kNq48epWGh(=x+bz?(o3)H~cqh{C_ zb@)cu^4X}FEJSZyj)`$S>hauRJ&oFu+t&N2m41SHJl$_>M!IpPp#aoCa-$k5fEqw0 z)Qsw)R;CZ?v=2gmoQ@js7SwMX>eR`wMp!T8^M+Ts0AL>;BU2AB(T;84_z zm!Vc@Cu$2$pz7a64fHMQkU2k?dVZLgWB_VFVK!X?laj7r^J}B$`ENl)9rQspI105# z6HrUH5H+J^sE*d52Cxq`lMASs-bBst1!@AHQ3J>^-h3M_fGTf~+PXgI`TQS9L?fGs z5jY36#HUd!Z~--=N0n%DRGc>0_w*3sHId^g)T9M=Eix*M#9-to6x2XCVrfQ!4XLr{DB6Q;wxsD>|FAEP?{gnGRE zf3i!A`AFACO=y(OpJZKx+S<+Nk9#o`Z~esjE0S!U*_$G$5!XS_o}(HZfm+%LsJ&f` zTCr8A!?gjmQrl2Vd>FNbzvH)f4Rv3o`KG;SRCyye5mjh~dGQpg;g6`Lj<>*k>Lo%w z-~QHc)R`%bYPdEQz(!aa$D=wpjT+!3)I@GrAE54Y|4l?Ae~%f_d!bqSK-3v1fm(@Z zn{J6}us3GFftVg=UQK!blwrn@5;RC1v97k>8?>7H3YJzd7iQLB$^zXbTqKXkq%n}vBaMI;b zThkl!<8WL43#x(rr~#fsHGIpKKeWC^ZBhKCrkyOP0p_;p2y`o>G!Zpa$yR7!)6G#^ z(*-s2;WjiE8&ZWRIOIs25wZW#-p+Wl`^mPRm$-bugTaEI13* z(H7JS>_>I*5;eeh%gs#vP)nQl&BR;hk6Qv(I1Q1bYs;0 z?oLFsMBkwro`8Ch{AeqjMy<>rsE!_?2J{wHKiMiX(Day-bQVY)EO{tuZwsJiQq$%)M|IH7=J!FZ;3(9YS%+Gwo2UW&iF&-B zq55&HF)QWgk^Rq1#Gis7OoEj#DaN2yra9)oo~RklLN&Yxeef`9K!r6{$_!{cQyQmRALpAsrwGzJT%*td(Jw}n34eOvL z&=WO*!RUkIQ0>mb6u1C&XxF1#8C!|yvx z38zMlP8#yK+7;UBi*9n@p^1U0ba8_aVXgnGV9q0UA< z)P3DB6#JoOycpH)2GoFdq6T;ZHIU0T|JDZ9zY!TP$k2_|Hk!R`gu0&q44IL=^z3Jac zw9D*mN>oR|sD{IBx;Scvs)L^I{{x7qfsv@anqbrOQKx?eCdVD94vyLM6HG(;18QKtd(F4!Ak>5^pk`bL z)lPHt!)~bh!}qfO+KX9asG-%UL$cp`8g=7U)BvBLPWLO+%v0?%D^?smhYrPK)OAupJ6x=XYF(Ig_20fely}LYwYQg04c)ipPq8rR4_FH$4w$7JjzdVV zLM?UJLGz7gF@}=9f^{&#Aznt<5UXQq_hFWWNK4F$dr>cvI4pyHNBAJZx|j!-V>Y~i z+3^+j$8<-{*X}78PI?b&rq59mNqEeBc%?xNyaZN7_YXw01(z@kAEVxU>5rSG%!%5P zaGQ?AK+=`42X;iA<{P%W_zAoBs2SHmy+@X#&QOMvro9kkfNrNC5zVM7Cc|&BF7`z) zJc;V)cdU*TPnj3eRMgY49z#_RwN-C05&nxcFyU$Qn~yrE^di&>|Aq1N{0E*fU$29( z6$K5^4|k#(JdG*vJbL3@EQC+7Ee4)7-w(!NGScfX1b1OgyoXh>;5ptQ=td3XfYS8u z`2J@0x*n>7nOF@MU{ZX7n)zF6h2Ks26bvW-25QApoHw>XE&X;Ziar<2gesyx=|<>- z{n4$AF+?=epHTx?hg!mIHh(YXCVd#2;@>tMeUaBJ=>e$wl3y~PA?Yv==^m)Vy#Te9 zpHYvY*Ja0Pf&Q0Se|0pJjDk28V{s2EKgSi5ABM_riG%P6s>2Fb&0f~T)})7`^6#M^ zK0`evu0PC+D-fT%I766&{KD5+{~#hwuA7g~VVI8e2Gl7(hB^~ZQF~eIhFSXgScUXs z?2U!u`1uf5;Zcmb$swg9uUqDj2HrLkDTUgyUYH)2x{2f@vImRcT~tSz@0g|Qi1|q$ zN7eg?I*b8#%{QP3)C6i^UF?OK@fg-%0Dqz;RPaw`j@3~eN8UH>x$6;$A!7h$!P6Lk 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 KcVAb3*Z%-Pj(6?= delta 23702 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 diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index 7ec537032..f1cbc5362 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-10 17:57\n" "Last-Translator: Mouse Reeve \n" "Language-Team: French\n" "Language: fr\n" @@ -46,6 +46,10 @@ msgstr "Sans limite" msgid "Reading finish date cannot be before start date." msgstr "La date de fin de lecture ne peut pas être antérieure à la date de début." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "La date de fin de lecture ne peut pas être antérieure à la date de début." + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Un compte du même nom existe déjà" @@ -70,8 +74,8 @@ msgstr "Ordre de la liste" msgid "Book Title" msgstr "Titre du livre" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Note" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Ajouter un autre auteur ou autrice" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Couverture" @@ -1709,13 +1713,13 @@ msgstr "Ajouter à vos livres" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "À lire" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Lectures en cours" @@ -1724,10 +1728,15 @@ msgstr "Lectures en cours" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lu" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "Lecture interrompue" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Que lisez‑vous ?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Ligne" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Titre" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Clé Openlibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Auteur/autrice" @@ -2988,6 +2997,11 @@ msgstr "Terminer \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Commencer \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Interrompre la lecture de « %(book_title)s »" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Mettre à jour les dates de lecture pour « %(title)s »" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Lecture commencée le" @@ -3020,7 +3035,7 @@ msgstr "Lecture commencée le" msgid "Progress" msgstr "Progression" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Progression :" msgid "finished" msgstr "terminé" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "interrompu" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Montrer toutes les progressions" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Supprimer cette mise à jour" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "commencé" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Modifier les date de lecture" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Supprimer ces dates de lecture" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Profil utilisateur·rice" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Tous les livres" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s livre" msgstr[1] "%(formatted_count)s livres" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(affichage de %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Modifier l’étagère" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Supprimer l’étagère" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Date d’ajout" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Commencé" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Terminé" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "Jusqu’à" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Cette étagère est vide" @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Facultatif)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Progression de la mise à jour" @@ -4737,6 +4761,17 @@ msgstr "Progression de la mise à jour" msgid "Start \"%(book_title)s\"" msgstr "Commencer « %(book_title)s »" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Interrompre la lecture de « %(book_title)s »" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "Lecture interrompue" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Déplacer le livre" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Commencer la lecture" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Je veux le lire" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Retirer de %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Retirer de" @@ -4808,7 +4843,12 @@ msgstr "Retirer de" msgid "More shelves" msgstr "Plus d’étagères" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "Interrompre la lecture" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Terminer la lecture" @@ -4903,6 +4943,16 @@ msgstr "a publié une critique de %(book)s par %(book)s" msgstr "a critiqué %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "a interrompu la lecture de %(book)s par %(author_name)s" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "a interrompu la lecture de %(book)s" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s ne suit personne" msgid "Edit profile" msgstr "Modifier le profil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Voir les %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Voir tous les livres" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Défi lecture pour %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Activité du compte" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Flux RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Aucune activité pour l’instant !" diff --git a/locale/gl_ES/LC_MESSAGES/django.mo b/locale/gl_ES/LC_MESSAGES/django.mo index 7f76d9eef71720793e7517b3f59f9bb4709b56a8..08eca4a48ab8511f830eb5b0abf6834411c66cff 100644 GIT binary patch delta 24163 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\n" "Language-Team: Galician\n" "Language: gl\n" @@ -46,6 +46,10 @@ msgstr "Sen límite" msgid "Reading finish date cannot be before start date." msgstr "A data final da lectura non pode ser anterior á de inicio." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "A data do fin da lectura non pode ser anterior á de inicio." + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Xa existe unha usuaria con este identificador" @@ -70,8 +74,8 @@ msgstr "Orde da lista" msgid "Book Title" msgstr "Título do libro" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Puntuación" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Engade outra Autora" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Portada" @@ -1709,13 +1713,13 @@ msgstr "Engadir aos teus libros" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Pendentes" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Lectura actual" @@ -1724,10 +1728,15 @@ msgstr "Lectura actual" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lido" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "Deixei de ler" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Que estás a ler?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Fila" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Título" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Chave en Openlibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor" @@ -2988,6 +2997,11 @@ msgstr "Acabei \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Comecei \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Deixar de ler \"%(book_title)s\"" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Actualizar as datas de lectura para \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Comecei a ler" @@ -3020,7 +3035,7 @@ msgstr "Comecei a ler" msgid "Progress" msgstr "Progreso" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Actualizacións da lectura:" msgid "finished" msgstr "rematado" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "detido" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Mostrar tódalas actualizacións" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Eliminar esta actualización da lectura" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "iniciado" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Editar datas da lectura" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Eliminar estas datas da lectura" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Perfil da usuaria" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Tódolos libros" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s libro" msgstr[1] "%(formatted_count)s libros" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(mostrando %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Editar estante" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Eliminar estante" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "No estante" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Comezado" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Rematado" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "Ata" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Este estante esta baleiro." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Optativo)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Actualización do progreso" @@ -4737,6 +4761,17 @@ msgstr "Actualización do progreso" msgid "Start \"%(book_title)s\"" msgstr "Comecei a ler \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "Deixar de ler \"%(book_title)s\"" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "Deixei de ler" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Mover libro" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Comezar a ler" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Quero ler" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Eliminar de %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Eliminar de" @@ -4808,7 +4843,12 @@ msgstr "Eliminar de" msgid "More shelves" msgstr "Máis estantes" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "Deixar de ler" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Rematar a lectura" @@ -4903,6 +4943,16 @@ msgstr "recensionou %(book)s de %(book)s" msgstr "recensionou %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "deixei de ler %(book)s de %(author_name)s" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "deixei de ler %(book)s" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s non segue a ninguén" msgid "Edit profile" msgstr "Editar perfil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Ver tódolos %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Ver tódolos libros" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Obxectivo de Lectura para %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Actividade da usuaria" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Fonte RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Sen actividade!" diff --git a/locale/it_IT/LC_MESSAGES/django.mo b/locale/it_IT/LC_MESSAGES/django.mo index 25657558b66666de4c3e924b32accca50c522b3f..97519011a01c19ea7ebe7f36b861c56d01caabd4 100644 GIT binary patch delta 25 hcmX?lgZ1bQ)(y2cxy*D83>6FvtV~Tex8K}12>^}v3ZMW0 delta 25 hcmX?lgZ1bQ)(y2cxlDD9OcV?ZtqjaIx8K}12>^}~3ZVc1 diff --git a/locale/it_IT/LC_MESSAGES/django.po b/locale/it_IT/LC_MESSAGES/django.po index 5e53007b2..9ee240bf2 100644 --- a/locale/it_IT/LC_MESSAGES/django.po +++ b/locale/it_IT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Italian\n" "Language: it\n" @@ -46,6 +46,10 @@ msgstr "Illimitato" msgid "Reading finish date cannot be before start date." msgstr "La data di fine lettura non può essere precedente alla data di inizio." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Esiste già un utente con questo nome utente" @@ -70,8 +74,8 @@ msgstr "Ordina Lista" msgid "Book Title" msgstr "Titolo del libro" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Valutazione" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Aggiungi un altro autore" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Copertina" @@ -1709,13 +1713,13 @@ msgstr "Aggiungi ai tuoi libri" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Da leggere" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Letture correnti" @@ -1724,10 +1728,15 @@ msgstr "Letture correnti" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Letti" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Cosa stai leggendo?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Riga" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Titolo" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Chiave OpenLibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autore" @@ -2988,6 +2997,11 @@ msgstr "Termina \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Inizia \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Aggiorna date di lettura per \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Inizia la lettura" @@ -3020,7 +3035,7 @@ msgstr "Inizia la lettura" msgid "Progress" msgstr "Avanzamento" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Aggiornamento progressi:" msgid "finished" msgstr "completato" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Mostra tutti gli aggiornamenti" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Elimina questo aggiornamento" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "iniziato" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Modifica data di lettura" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Elimina queste date di lettura" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Profilo utente" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Tutti i libri" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s libro" msgstr[1] "%(formatted_count)s libri" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(mostra %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Modifica scaffale" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Elimina scaffale" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Scaffali" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Iniziato" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Completato" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Questo scaffale è vuoto." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Opzionale)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Aggiornamento in corso" @@ -4737,6 +4761,17 @@ msgstr "Aggiornamento in corso" msgid "Start \"%(book_title)s\"" msgstr "Inizia \"%(book_title)s \"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Sposta libro" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Inizia la lettura" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Vuoi leggere" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Rimuovi da %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Rimuovi da" @@ -4808,7 +4843,12 @@ msgstr "Rimuovi da" msgid "More shelves" msgstr "Altri scaffali" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Finito di leggere" @@ -4903,6 +4943,16 @@ msgstr "ha recensito %(book)s di %(book)s" msgstr "ha recensito %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s non sta seguendo nessun utente" msgid "Edit profile" msgstr "Modifica profilo" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Visualizza tutti i %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Visualizza tutti i libri" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Obiettivo di lettura %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Attività dell’utente" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Feed RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Ancora nessuna attività!" diff --git a/locale/lt_LT/LC_MESSAGES/django.mo b/locale/lt_LT/LC_MESSAGES/django.mo index cccee2cfc7740a9e736856d27b0052d4492deca3..91350fa48d824d18b0aa12728b334123d679613e 100644 GIT binary patch delta 25 hcmX^2iuK$p)(y2cxy*D83>6FvtV~Tex8FQI8vv5y3g`d; delta 25 hcmX^2iuK$p)(y2cxlDD9OcV?ZtqjaIx8FQI8vv623h4j< diff --git a/locale/lt_LT/LC_MESSAGES/django.po b/locale/lt_LT/LC_MESSAGES/django.po index a2a83ca86..0f33bc60c 100644 --- a/locale/lt_LT/LC_MESSAGES/django.po +++ b/locale/lt_LT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Lithuanian\n" "Language: lt\n" @@ -46,6 +46,10 @@ msgstr "Neribota" msgid "Reading finish date cannot be before start date." msgstr "Skaitymo pabaigos data negali būti prieš skaitymo pradžios datą." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Toks naudotojo vardas jau egzistuoja" @@ -70,8 +74,8 @@ msgstr "Kaip pridėta į sąrašą" msgid "Book Title" msgstr "Knygos antraštė" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Įvertinimas" @@ -1087,7 +1091,7 @@ msgid "Add Another Author" msgstr "Pridėti dar vieną autorių" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Viršelis" @@ -1725,13 +1729,13 @@ msgstr "Pridėti prie savo knygų" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Norimos perskaityti" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Šiuo metu skaitomos" @@ -1740,10 +1744,15 @@ msgstr "Šiuo metu skaitomos" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Perskaitytos" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Ką skaitome?" @@ -2079,8 +2088,8 @@ msgid "Row" msgstr "Eilutė" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Pavadinimas" @@ -2093,8 +2102,8 @@ msgid "Openlibrary key" msgstr "„Openlibrary“ raktas" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autorius" @@ -3012,6 +3021,11 @@ msgstr "Užbaigti „%(book_title)s“" msgid "Start \"%(book_title)s\"" msgstr "Pradėti „%(book_title)s“" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3036,6 +3050,7 @@ msgstr "Atnaujinkite knygos „%(title)s“ skaitymo datas" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Pradėjo skaityti" @@ -3044,7 +3059,7 @@ msgstr "Pradėjo skaityti" msgid "Progress" msgstr "Progresas" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3058,23 +3073,27 @@ msgstr "Informacija apie progresą:" msgid "finished" msgstr "baigta" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Rodyti visus naujinius" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Ištrinti progreso naujinį" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "pradėta" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Redaguoti skaitymo datas" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Ištrinti šias skaitymo datas" @@ -4391,11 +4410,11 @@ msgid "User profile" msgstr "Nario paskyra" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Visos knygos" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" @@ -4404,35 +4423,40 @@ msgstr[1] "%(formatted_count)s knygos" msgstr[2] "%(formatted_count)s knygų" msgstr[3] "%(formatted_count)s knygos" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(rodoma %(start)s–%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Redaguoti lentyną" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Ištrinti lentyną" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Sudėta į lentynas" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Pradėta" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Baigta" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Ši lentyna tuščia." @@ -4774,7 +4798,7 @@ msgid "(Optional)" msgstr "(Nebūtina)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Atnaujinti progresą" @@ -4783,6 +4807,17 @@ msgstr "Atnaujinti progresą" msgid "Start \"%(book_title)s\"" msgstr "Pradėti „%(book_title)s“" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4830,23 +4865,23 @@ msgstr "Perkelti knygą" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Pradėti skaityti" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Noriu perskaityti" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Pašalinti iš %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Panaikinti iš" @@ -4854,7 +4889,12 @@ msgstr "Panaikinti iš" msgid "More shelves" msgstr "Daugiau lentynų" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Baigti skaityti" @@ -4949,6 +4989,16 @@ msgstr "apžvelgė autoriaus %(author_name)s kny msgid "reviewed %(book)s" msgstr "apžvelgė %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5089,29 +5139,29 @@ msgstr "%(username)s nieko neseka" msgid "Edit profile" msgstr "Redaguoti paskyrą" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Žiūrėti visas %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Žiūrėti visas knygas" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "%(current_year)s skaitymo tikslas" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Naudotojo aktyvumas" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS srautas" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Įrašų dar nėra" diff --git a/locale/no_NO/LC_MESSAGES/django.mo b/locale/no_NO/LC_MESSAGES/django.mo index 5ed2511ca983f6df576a7eecf3a41cbd3f52325e..b7357cd251b9dda4234bdd81d7c354b4967af6d6 100644 GIT binary patch delta 25 hcmccgn&r}KmJJ*CbD8NH7%CVTSecq`-o0PE3;>jj3Qqt4 delta 25 hcmccgn&r}KmJJ*CbD8QInJ5?-S{aya-o0PE3;>j;3Qzz5 diff --git a/locale/no_NO/LC_MESSAGES/django.po b/locale/no_NO/LC_MESSAGES/django.po index 3d94300af..4434f489b 100644 --- a/locale/no_NO/LC_MESSAGES/django.po +++ b/locale/no_NO/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Norwegian\n" "Language: no\n" @@ -46,6 +46,10 @@ msgstr "Ubegrenset" msgid "Reading finish date cannot be before start date." msgstr "Sluttdato kan ikke være før startdato." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "" @@ -70,8 +74,8 @@ msgstr "Liste rekkefølge" msgid "Book Title" msgstr "Boktittel" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Vurdering" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Legg til enda en forfatter" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Omslag" @@ -1709,13 +1713,13 @@ msgstr "Legg til i bøkene dine" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Å lese" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Leser nå" @@ -1724,10 +1728,15 @@ msgstr "Leser nå" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lest" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Hva er det du leser nå?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Rad" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Tittel" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Openlibrary nøkkel" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Forfatter" @@ -2988,6 +2997,11 @@ msgstr "Fullfør \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Start \"%(book_title)s" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Oppdatér lesedatoer for \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Begynte å lese" @@ -3020,7 +3035,7 @@ msgstr "Begynte å lese" msgid "Progress" msgstr "Fremdrift" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Fremdriftsoppdateringer:" msgid "finished" msgstr "ferdig" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Vis alle oppdateringer" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Slett denne fremgangsoppdateringen" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "startet" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Rediger lesedatoer" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Slett disse lesedatoene" @@ -4357,46 +4376,51 @@ msgid "User profile" msgstr "Brukerprofil" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Alle bøker" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s bok" msgstr[1] "%(formatted_count)s bøker" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(viser %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Rediger hylle" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Slett hylle" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Lagt på hylla" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Startet" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Fullført" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Denne hylla er tom." @@ -4726,7 +4750,7 @@ msgid "(Optional)" msgstr "(Valgfritt)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Oppdater fremgang" @@ -4735,6 +4759,17 @@ msgstr "Oppdater fremgang" msgid "Start \"%(book_title)s\"" msgstr "Start \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4782,23 +4817,23 @@ msgstr "Flytt bok" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Begynn å lese" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Ønsker å lese" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Fjern fra %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Fjern fra" @@ -4806,7 +4841,12 @@ msgstr "Fjern fra" msgid "More shelves" msgstr "Flere hyller" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Fullfør lesing" @@ -4901,6 +4941,16 @@ msgstr "anmeldte %(book)s av %(book)s" msgstr "anmeldte %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5041,29 +5091,29 @@ msgstr "%(username)s følger ingen andre medlemmer" msgid "Edit profile" msgstr "Rediger profil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Vis alle %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Se alle bøker" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "%(current_year)s lesemål" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Brukeraktivitet" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS strøm" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Ingen aktivitet enda!" diff --git a/locale/pt_BR/LC_MESSAGES/django.mo b/locale/pt_BR/LC_MESSAGES/django.mo index a67f03752977dd5bf848eb84e8426cff2b52f4c2..917f0cd45500c157b2d0c5e668b08f3d42ed3a21 100644 GIT binary patch delta 25 hcmX?liS_6u)(y2cxy*D83>6FvtV~Tex8K~?4*-nj3XuQ+ delta 25 hcmX?liS_6u)(y2cxlDD9OcV?ZtqjaIx8K~?4*-n;3X%W- diff --git a/locale/pt_BR/LC_MESSAGES/django.po b/locale/pt_BR/LC_MESSAGES/django.po index 371e46ec6..aa0534052 100644 --- a/locale/pt_BR/LC_MESSAGES/django.po +++ b/locale/pt_BR/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Portuguese, Brazilian\n" "Language: pt\n" @@ -46,6 +46,10 @@ msgstr "Ilimitado" msgid "Reading finish date cannot be before start date." msgstr "A data de término da leitura não pode ser anterior a de início." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Um usuário com este nome já existe" @@ -70,8 +74,8 @@ msgstr "Ordem de inserção" msgid "Book Title" msgstr "Título do livro" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Avaliação" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Adicionar outro/a autor/a" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Capa" @@ -1709,13 +1713,13 @@ msgstr "Adicionar aos seus livros" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Quero ler" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Lendo atualmente" @@ -1724,10 +1728,15 @@ msgstr "Lendo atualmente" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lido" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "O que você está lendo?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Linha" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Título" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Chave Openlibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor/a" @@ -2988,6 +2997,11 @@ msgstr "Terminar \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Começar \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Atualizar datas de leitura de \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Começou a ler" @@ -3020,7 +3035,7 @@ msgstr "Começou a ler" msgid "Progress" msgstr "Andamento" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Registro de leitura:" msgid "finished" msgstr "terminado" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Mostrar andamento da leitura" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Excluir esta atualização de andamento" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "iniciado" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Editar registro de leitura" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Excluir estas datas de leitura" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Perfil do usuário" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Todos os livros" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s livro" msgstr[1] "%(formatted_count)s livros" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(mostrando %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Editar estante" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Excluir estante" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Adicionado" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Iniciado" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Terminado" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Esta estante está vazia." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Opcional)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Atualizar andamento" @@ -4737,6 +4761,17 @@ msgstr "Atualizar andamento" msgid "Start \"%(book_title)s\"" msgstr "Começar \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Mover livro" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Começar a ler" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Quero ler" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Remover de %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Remover de" @@ -4808,7 +4843,12 @@ msgstr "Remover de" msgid "More shelves" msgstr "Mais estantes" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Terminar de ler" @@ -4903,6 +4943,16 @@ msgstr "resenhou %(book)s de %(book)s" msgstr "resenhou %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s não segue ninguém" msgid "Edit profile" msgstr "Editar perfil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Ver todos os %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Ver todos os livros" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Meta de leitura para %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Atividade do usuário" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Feed RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Nenhuma atividade ainda!" diff --git a/locale/pt_PT/LC_MESSAGES/django.mo b/locale/pt_PT/LC_MESSAGES/django.mo index 640fa53364f694b3920832f90c1245d5261bcb29..07b9f009f22aff959a24c2043023b6f6c0c35380 100644 GIT binary patch delta 25 hcmeymg!StZ)(sJ-xy*D83>6FvtV~TeC!H2<2LOls348zm delta 25 hcmeymg!StZ)(sJ-xlDD9OcV?ZtqjaIC!H2<2LOl{34H(n diff --git a/locale/pt_PT/LC_MESSAGES/django.po b/locale/pt_PT/LC_MESSAGES/django.po index fa7c865aa..cdfb2b890 100644 --- a/locale/pt_PT/LC_MESSAGES/django.po +++ b/locale/pt_PT/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Portuguese\n" "Language: pt\n" @@ -46,6 +46,10 @@ msgstr "Ilimitado" msgid "Reading finish date cannot be before start date." msgstr "A data final de leitura não pode ser anterior à data de início." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Já existe um utilizador com este nome" @@ -70,8 +74,8 @@ msgstr "Ordem da Lista" msgid "Book Title" msgstr "Título do livro" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Classificação" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Adicionar outro autor(a)" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Capa" @@ -1709,13 +1713,13 @@ msgstr "Adicionar aos teus livros" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Para Ler" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Leituras atuais" @@ -1724,10 +1728,15 @@ msgstr "Leituras atuais" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lido" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "O que andas a ler?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Linha" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Título" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Id da Openlibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor(a)" @@ -2988,6 +2997,11 @@ msgstr "Concluir \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Começar \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Atualizar datas de leitura para \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Leitura iniciada" @@ -3020,7 +3035,7 @@ msgstr "Leitura iniciada" msgid "Progress" msgstr "Progresso" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Atualizações do progresso:" msgid "finished" msgstr "concluído" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Mostrar todas as atualizações" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Excluir esta atualização do progresso" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "iniciado" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Editar datas de leitura" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Excluir estas datas de leitura" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Perfil de utilizador" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Todos os livros" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s livro" msgstr[1] "%(formatted_count)s livros" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(a exibir %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Editar prateleira" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Apagar prateleira" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Arquivado" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Iniciado" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Concluído" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Esta prateleira está vazia." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Opcional)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Atualizar progresso" @@ -4737,6 +4761,17 @@ msgstr "Atualizar progresso" msgid "Start \"%(book_title)s\"" msgstr "Começar \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Mover livro" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Começar a ler" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Quero ler" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Remover de %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Remover de" @@ -4808,7 +4843,12 @@ msgstr "Remover de" msgid "More shelves" msgstr "Mais prateleiras" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Terminar leitura" @@ -4903,6 +4943,16 @@ msgstr "" msgid "reviewed %(book)s" msgstr "criticou %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s não está a seguir ninguém" msgid "Edit profile" msgstr "Editar perfil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Ver todas as %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Ver todos os livros" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Objetivo de leitura de %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Atividade do Utilizador" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS Feed" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Ainda sem atividade!" diff --git a/locale/ro_RO/LC_MESSAGES/django.mo b/locale/ro_RO/LC_MESSAGES/django.mo index e9b278ecbb2e3d98a75cc249f521826394ea599b..4134a5e337cb04a3f7bff620e4712f8b40c42ef7 100644 GIT binary patch delta 25 hcmezNnDyIZ)(y2cxy*D83>6FvtV~Tex8Ka40RWgy3eNxl delta 25 hcmezNnDyIZ)(y2cxlDD9OcV?ZtqjaIx8Ka40RWh23eW%m diff --git a/locale/ro_RO/LC_MESSAGES/django.po b/locale/ro_RO/LC_MESSAGES/django.po index 8d20397dd..0270a93fa 100644 --- a/locale/ro_RO/LC_MESSAGES/django.po +++ b/locale/ro_RO/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Romanian\n" "Language: ro\n" @@ -46,6 +46,10 @@ msgstr "Nelimitat" msgid "Reading finish date cannot be before start date." msgstr "Data de terminare a lecturii nu poate fi înainte de data de început." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "Un utilizator cu acest nume există deja" @@ -70,8 +74,8 @@ msgstr "Ordonează după listă" msgid "Book Title" msgstr "Titlul cărții" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Rating" @@ -1081,7 +1085,7 @@ msgid "Add Another Author" msgstr "Adăugați un alt autor" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Copertă" @@ -1717,13 +1721,13 @@ msgstr "Adăugați la cărțile dvs." #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "De citit" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Lectură în curs" @@ -1732,10 +1736,15 @@ msgstr "Lectură în curs" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Citite" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Ce citiți?" @@ -2067,8 +2076,8 @@ msgid "Row" msgstr "Linie" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Titlu" @@ -2081,8 +2090,8 @@ msgid "Openlibrary key" msgstr "Cheie OpenLibrary" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Autor" @@ -3000,6 +3009,11 @@ msgstr "Terminați „%(book_title)s”" msgid "Start \"%(book_title)s\"" msgstr "Începeți „%(book_title)s”" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3024,6 +3038,7 @@ msgstr "Actualizați datele de lectură pentru „%(title)s”" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "A început lectura" @@ -3032,7 +3047,7 @@ msgstr "A început lectura" msgid "Progress" msgstr "Progres" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3046,23 +3061,27 @@ msgstr "Progresie:" msgid "finished" msgstr "terminat" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Afișați toate actualizările" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Ștergeți această actualizare" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "începută" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Editați datele de lectură" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Ștergeți aceste date de lectură" @@ -4375,11 +4394,11 @@ msgid "User profile" msgstr "Profilul utilizatorului" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Toate cărțile" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" @@ -4387,35 +4406,40 @@ msgstr[0] "%(formatted_count)s carte" msgstr[1] "" msgstr[2] "%(formatted_count)s cărți" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(se afișează %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Editați raft" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Ștergeți raft" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Pusă pe raft" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Începută" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Terminată" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Acest raft este gol." @@ -4751,7 +4775,7 @@ msgid "(Optional)" msgstr "(Opțional)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Actualizați progresul" @@ -4760,6 +4784,17 @@ msgstr "Actualizați progresul" msgid "Start \"%(book_title)s\"" msgstr "Începeți „%(book_title)s”" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4807,23 +4842,23 @@ msgstr "Mutați carte" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Începeți să citiți" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Vreau să citesc" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Înlăturați de pe %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Înlăturați din" @@ -4831,7 +4866,12 @@ msgstr "Înlăturați din" msgid "More shelves" msgstr "Mai multe rafturi" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Terminați de citit" @@ -4926,6 +4966,16 @@ msgstr "a evaluat %(book)s de %(book)s" msgstr "a evaluat %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5066,29 +5116,29 @@ msgstr "%(username)s nu urmărește pe nimeni" msgid "Edit profile" msgstr "Editați profil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Vizualizați toate %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Vizualizați toate cărțile" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "Obiectivul de lectură din %(current_year)s" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Activitatea utilizatorului" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "Flux RSS" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Încă nicio activitate!" diff --git a/locale/sv_SE/LC_MESSAGES/django.mo b/locale/sv_SE/LC_MESSAGES/django.mo index 0779ff8e38ab3604aaefede79a801676e6d7ed26..e565450b1c0af541b4d62126c8bf3c95028778b2 100644 GIT binary patch delta 25 hcmbPmiFLvy)(xCDxy*D83>6FvtV~Te3*Y?P4*+?w34Q\n" "Language-Team: Swedish\n" "Language: sv\n" @@ -46,6 +46,10 @@ msgstr "Obegränsad" msgid "Reading finish date cannot be before start date." msgstr "Slutdatum för läsning kan inte vara före startdatum." +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "En användare med det användarnamnet existerar redan" @@ -70,8 +74,8 @@ msgstr "Listordning" msgid "Book Title" msgstr "Bokens titel" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "Betyg" @@ -1075,7 +1079,7 @@ msgid "Add Another Author" msgstr "Lägg till en annan författare" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "Omslag" @@ -1709,13 +1713,13 @@ msgstr "Lägg till i dina böcker" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "Att läsa" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "Läser just nu" @@ -1724,10 +1728,15 @@ msgstr "Läser just nu" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "Lästa" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "Vad läser du?" @@ -2055,8 +2064,8 @@ msgid "Row" msgstr "Rad" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "Titel" @@ -2069,8 +2078,8 @@ msgid "Openlibrary key" msgstr "Openlibrary-nyckel" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "Författare" @@ -2988,6 +2997,11 @@ msgstr "Avsluta \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" msgstr "Påbörja \"%(book_title)s\"" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3012,6 +3026,7 @@ msgstr "Uppdatera läsdatum för \"%(title)s\"" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "Började läsa" @@ -3020,7 +3035,7 @@ msgstr "Började läsa" msgid "Progress" msgstr "Förlopp" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3034,23 +3049,27 @@ msgstr "Förloppsuppdateringar:" msgid "finished" msgstr "avslutad" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "Visa alla uppdateringar" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "Ta bort den här förloppsuppdateringen" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "påbörjades" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "Redigera läsdatum" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "Ta bort de här läsdatumen" @@ -4359,46 +4378,51 @@ msgid "User profile" msgstr "Användarprofil" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "Alla böcker" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s bok" msgstr[1] "%(formatted_count)s böcker" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(visar %(start)s-%(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "Redigera hylla" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "Ta bort hylla" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "Lagd på hyllan" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "Påbörjade" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "Avslutade" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "Den här hyllan är tom." @@ -4728,7 +4752,7 @@ msgid "(Optional)" msgstr "(Valfritt)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "Uppdateringsförlopp" @@ -4737,6 +4761,17 @@ msgstr "Uppdateringsförlopp" msgid "Start \"%(book_title)s\"" msgstr "Börja \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4784,23 +4819,23 @@ msgstr "Flytta boken" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "Börja läsa" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "Vill läsa" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "Ta bort från %(name)s" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "Ta bort från" @@ -4808,7 +4843,12 @@ msgstr "Ta bort från" msgid "More shelves" msgstr "Mer hyllor" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "Sluta läs" @@ -4903,6 +4943,16 @@ msgstr "recenserade %(book)s av %(book)s" msgstr "recenserade %(book)s" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5043,29 +5093,29 @@ msgstr "%(username)s följer inte någon användare" msgid "Edit profile" msgstr "Redigera profil" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "Visa alla %(size)s" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "Visa alla böcker" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "%(current_year)s läsmål" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "Användaraktivitet" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS-flöde" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "Inga aktiviteter än!" diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index 4c2a6c1f556905de752d63e136b4b7d802a1c56c..992a6957659f17dfe86ca464906e6abe1c4f8d6f 100644 GIT binary patch delta 25 hcmZ3soORi9)(y2cxy*D83>6FvtV~Tex8Ibn0swwf2}u9| delta 25 hcmZ3soORi9)(y2cxlDD9OcV?ZtqjaIx8Ibn0sww)2}%F} diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 8bd28ceab..5eb151b0a 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Chinese Simplified\n" "Language: zh\n" @@ -46,6 +46,10 @@ msgstr "不受限" msgid "Reading finish date cannot be before start date." msgstr "读完日期不得早于开始日期。" +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "使用此用户名的用户已存在" @@ -70,8 +74,8 @@ msgstr "列表顺序" msgid "Book Title" msgstr "书名" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "评价" @@ -1069,7 +1073,7 @@ msgid "Add Another Author" msgstr "添加其他作者" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "封面" @@ -1701,13 +1705,13 @@ msgstr "添加到您的书籍中" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "想读" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "在读" @@ -1716,10 +1720,15 @@ msgstr "在读" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "读过" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "你在阅读什么?" @@ -2043,8 +2052,8 @@ msgid "Row" msgstr "行" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "标题" @@ -2057,8 +2066,8 @@ msgid "Openlibrary key" msgstr "Openlibrary key" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "作者" @@ -2976,6 +2985,11 @@ msgstr "完成《%(book_title)s》" msgid "Start \"%(book_title)s\"" msgstr "开始《%(book_title)s》" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3000,6 +3014,7 @@ msgstr "更新 “%(title)s” 的阅读日期" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "已开始阅读" @@ -3008,7 +3023,7 @@ msgstr "已开始阅读" msgid "Progress" msgstr "进度" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3022,23 +3037,27 @@ msgstr "进度更新:" msgid "finished" msgstr "已完成" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "显示所有更新" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "删除此进度更新" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "已开始" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "编辑阅读日期" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "删除这些阅读日期" @@ -4343,45 +4362,50 @@ msgid "User profile" msgstr "用户个人资料" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "所有书目" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "%(formatted_count)s 本书籍" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "(正在显示 %(start)s 到 %(end)s)" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "编辑书架" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "删除书架" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "上架时间" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "开始时间" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "完成时间" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "此书架是空的。" @@ -4705,7 +4729,7 @@ msgid "(Optional)" msgstr "(可选)" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "更新进度" @@ -4714,6 +4738,17 @@ msgstr "更新进度" msgid "Start \"%(book_title)s\"" msgstr "开始《%(book_title)s》" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4761,23 +4796,23 @@ msgstr "移动书目" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "开始阅读" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "想要阅读" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "从 %(name)s 移除" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "移除自" @@ -4785,7 +4820,12 @@ msgstr "移除自" msgid "More shelves" msgstr "更多书架" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "完成阅读" @@ -4880,6 +4920,16 @@ msgstr "写了 %(author_name)s%(book)s" msgstr "为 %(book)s 撰写了书评" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5020,29 +5070,29 @@ msgstr "%(username)s 没有关注任何用户" msgid "Edit profile" msgstr "编辑个人资料" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "查看所有 %(size)s 本" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "查看所有书目" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "%(current_year)s 阅读目标" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "用户活动" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS 流" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "还没有活动!" diff --git a/locale/zh_Hant/LC_MESSAGES/django.mo b/locale/zh_Hant/LC_MESSAGES/django.mo index 20be041a8670213f5d046504898a50751bba77e8..50dfadffcd25abf1102e2433aea4a1b756694f13 100644 GIT binary patch delta 25 gcmZ2DlWE~hrVTo=TxPlkh6)A-R;H$#&0@3l0cscrga7~l delta 25 gcmZ2DlWE~hrVTo=T&B84CJF|IRt9F9&0@3l0ctY`g#Z8m diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 14ad19a24..429a7f0b1 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-23 21:04+0000\n" -"PO-Revision-Date: 2022-05-24 01:06\n" +"POT-Creation-Date: 2022-05-31 23:50+0000\n" +"PO-Revision-Date: 2022-06-01 00:55\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Chinese Traditional\n" "Language: zh\n" @@ -46,6 +46,10 @@ msgstr "不受限" msgid "Reading finish date cannot be before start date." msgstr "" +#: bookwyrm/forms/forms.py:59 +msgid "Reading stopped date cannot be before start date." +msgstr "" + #: bookwyrm/forms/landing.py:32 msgid "User with this username already exists" msgstr "" @@ -70,8 +74,8 @@ msgstr "列表順序" msgid "Book Title" msgstr "書名" -#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:155 -#: bookwyrm/templates/shelf/shelf.html:187 +#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156 +#: bookwyrm/templates/shelf/shelf.html:188 #: bookwyrm/templates/snippets/create_status/review.html:32 msgid "Rating" msgstr "評價" @@ -1069,7 +1073,7 @@ msgid "Add Another Author" msgstr "" #: bookwyrm/templates/book/edit/edit_book_form.html:220 -#: bookwyrm/templates/shelf/shelf.html:146 +#: bookwyrm/templates/shelf/shelf.html:147 msgid "Cover" msgstr "封面" @@ -1701,13 +1705,13 @@ msgstr "" #: bookwyrm/templates/get_started/book_preview.html:10 #: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:33 -#: bookwyrm/templatetags/shelf_tags.py:46 +#: bookwyrm/templatetags/shelf_tags.py:48 msgid "To Read" msgstr "想讀" #: bookwyrm/templates/get_started/book_preview.html:11 #: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:34 -#: bookwyrm/templatetags/shelf_tags.py:48 +#: bookwyrm/templatetags/shelf_tags.py:50 msgid "Currently Reading" msgstr "在讀" @@ -1716,10 +1720,15 @@ msgstr "在讀" #: bookwyrm/templates/snippets/shelf_selector.html:47 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 -#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:50 +#: bookwyrm/templates/user/user.html:35 bookwyrm/templatetags/shelf_tags.py:52 msgid "Read" msgstr "讀過" +#: bookwyrm/templates/get_started/book_preview.html:13 +#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:36 +msgid "Stopped Reading" +msgstr "" + #: bookwyrm/templates/get_started/books.html:6 msgid "What are you reading?" msgstr "你在閱讀什麼?" @@ -2043,8 +2052,8 @@ msgid "Row" msgstr "" #: bookwyrm/templates/import/import_status.html:103 -#: bookwyrm/templates/shelf/shelf.html:147 -#: bookwyrm/templates/shelf/shelf.html:169 +#: bookwyrm/templates/shelf/shelf.html:148 +#: bookwyrm/templates/shelf/shelf.html:170 msgid "Title" msgstr "標題" @@ -2057,8 +2066,8 @@ msgid "Openlibrary key" msgstr "" #: bookwyrm/templates/import/import_status.html:114 -#: bookwyrm/templates/shelf/shelf.html:148 -#: bookwyrm/templates/shelf/shelf.html:172 +#: bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/templates/shelf/shelf.html:173 msgid "Author" msgstr "作者" @@ -2976,6 +2985,11 @@ msgstr "" msgid "Start \"%(book_title)s\"" msgstr "" +#: bookwyrm/templates/reading_progress/stop.html:5 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/reading_progress/want.html:5 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -3000,6 +3014,7 @@ msgstr "" #: bookwyrm/templates/readthrough/readthrough_modal.html:38 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:24 #: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:21 +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:24 msgid "Started reading" msgstr "已開始閱讀" @@ -3008,7 +3023,7 @@ msgstr "已開始閱讀" msgid "Progress" msgstr "進度" -#: bookwyrm/templates/readthrough/readthrough_form.html:24 +#: bookwyrm/templates/readthrough/readthrough_form.html:25 #: bookwyrm/templates/readthrough/readthrough_modal.html:63 #: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:32 msgid "Finished reading" @@ -3022,23 +3037,27 @@ msgstr "進度更新:" msgid "finished" msgstr "已完成" -#: bookwyrm/templates/readthrough/readthrough_list.html:25 +#: bookwyrm/templates/readthrough/readthrough_list.html:16 +msgid "stopped" +msgstr "" + +#: bookwyrm/templates/readthrough/readthrough_list.html:27 msgid "Show all updates" msgstr "顯示所有更新" -#: bookwyrm/templates/readthrough/readthrough_list.html:41 +#: bookwyrm/templates/readthrough/readthrough_list.html:43 msgid "Delete this progress update" msgstr "刪除此進度更新" -#: bookwyrm/templates/readthrough/readthrough_list.html:53 +#: bookwyrm/templates/readthrough/readthrough_list.html:55 msgid "started" msgstr "已開始" -#: bookwyrm/templates/readthrough/readthrough_list.html:60 +#: bookwyrm/templates/readthrough/readthrough_list.html:62 msgid "Edit read dates" msgstr "編輯閱讀日期" -#: bookwyrm/templates/readthrough/readthrough_list.html:68 +#: bookwyrm/templates/readthrough/readthrough_list.html:70 msgid "Delete these read dates" msgstr "刪除這些閱讀日期" @@ -4341,45 +4360,50 @@ msgid "User profile" msgstr "" #: bookwyrm/templates/shelf/shelf.html:39 -#: bookwyrm/templatetags/shelf_tags.py:44 bookwyrm/views/shelf/shelf.py:53 +#: bookwyrm/templatetags/shelf_tags.py:46 bookwyrm/views/shelf/shelf.py:53 msgid "All books" msgstr "所有書目" -#: bookwyrm/templates/shelf/shelf.html:96 +#: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" msgstr[0] "" -#: bookwyrm/templates/shelf/shelf.html:103 +#: bookwyrm/templates/shelf/shelf.html:104 #, python-format msgid "(showing %(start)s-%(end)s)" msgstr "" -#: bookwyrm/templates/shelf/shelf.html:115 +#: bookwyrm/templates/shelf/shelf.html:116 msgid "Edit shelf" msgstr "編輯書架" -#: bookwyrm/templates/shelf/shelf.html:123 +#: bookwyrm/templates/shelf/shelf.html:124 msgid "Delete shelf" msgstr "刪除書架" -#: bookwyrm/templates/shelf/shelf.html:151 -#: bookwyrm/templates/shelf/shelf.html:177 +#: bookwyrm/templates/shelf/shelf.html:152 +#: bookwyrm/templates/shelf/shelf.html:178 msgid "Shelved" msgstr "上架時間" -#: bookwyrm/templates/shelf/shelf.html:152 -#: bookwyrm/templates/shelf/shelf.html:180 +#: bookwyrm/templates/shelf/shelf.html:153 +#: bookwyrm/templates/shelf/shelf.html:181 msgid "Started" msgstr "開始時間" -#: bookwyrm/templates/shelf/shelf.html:153 -#: bookwyrm/templates/shelf/shelf.html:183 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 msgid "Finished" msgstr "完成時間" -#: bookwyrm/templates/shelf/shelf.html:209 +#: bookwyrm/templates/shelf/shelf.html:154 +#: bookwyrm/templates/shelf/shelf.html:184 +msgid "Until" +msgstr "" + +#: bookwyrm/templates/shelf/shelf.html:210 msgid "This shelf is empty." msgstr "此書架是空的。" @@ -4703,7 +4727,7 @@ msgid "(Optional)" msgstr "" #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61 msgid "Update progress" msgstr "更新進度" @@ -4712,6 +4736,17 @@ msgstr "更新進度" msgid "Start \"%(book_title)s\"" msgstr "開始 \"%(book_title)s\"" +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6 +#, python-format +msgid "Stop Reading \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32 +#: bookwyrm/templates/snippets/shelf_selector.html:54 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 +msgid "Stopped reading" +msgstr "" + #: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 #, python-format msgid "Want to Read \"%(book_title)s\"" @@ -4759,23 +4794,23 @@ msgstr "移動書目" #: bookwyrm/templates/snippets/shelf_selector.html:39 #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:24 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33 msgid "Start reading" msgstr "開始閱讀" -#: bookwyrm/templates/snippets/shelf_selector.html:54 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:38 +#: bookwyrm/templates/snippets/shelf_selector.html:61 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55 msgid "Want to read" msgstr "想要閱讀" -#: bookwyrm/templates/snippets/shelf_selector.html:75 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:66 +#: bookwyrm/templates/snippets/shelf_selector.html:82 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73 #, python-format msgid "Remove from %(name)s" msgstr "從 %(name)s 移除" -#: bookwyrm/templates/snippets/shelf_selector.html:88 +#: bookwyrm/templates/snippets/shelf_selector.html:95 msgid "Remove from" msgstr "" @@ -4783,7 +4818,12 @@ msgstr "" msgid "More shelves" msgstr "更多書架" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +msgid "Stop reading" +msgstr "" + +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40 msgid "Finish reading" msgstr "完成閱讀" @@ -4878,6 +4918,16 @@ msgstr "" msgid "reviewed %(book)s" msgstr "" +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10 +#, python-format +msgid "stopped reading %(book)s by %(author_name)s" +msgstr "" + +#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17 +#, python-format +msgid "stopped reading %(book)s" +msgstr "" + #: bookwyrm/templates/snippets/status/headers/to_read.html:10 #, python-format msgid "wants to read %(book)s by %(author_name)s" @@ -5018,29 +5068,29 @@ msgstr "%(username)s 沒有關注任何使用者" msgid "Edit profile" msgstr "編輯使用者資料" -#: bookwyrm/templates/user/user.html:37 +#: bookwyrm/templates/user/user.html:38 #, python-format msgid "View all %(size)s" msgstr "檢視所有 %(size)s 本" -#: bookwyrm/templates/user/user.html:51 +#: bookwyrm/templates/user/user.html:52 msgid "View all books" msgstr "檢視所有書目" -#: bookwyrm/templates/user/user.html:58 +#: bookwyrm/templates/user/user.html:59 #, python-format msgid "%(current_year)s Reading Goal" msgstr "" -#: bookwyrm/templates/user/user.html:65 +#: bookwyrm/templates/user/user.html:66 msgid "User Activity" msgstr "使用者活動" -#: bookwyrm/templates/user/user.html:69 +#: bookwyrm/templates/user/user.html:70 msgid "RSS feed" msgstr "RSS 訂閱" -#: bookwyrm/templates/user/user.html:80 +#: bookwyrm/templates/user/user.html:81 msgid "No activities yet!" msgstr "還沒有活動!" From f5d6a18ce0acea6a6ece14e09096c110cd49da21 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 10:49:57 -0700 Subject: [PATCH 035/167] Alphabetize list of software options in federated instances list --- bookwyrm/views/admin/federation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/admin/federation.py b/bookwyrm/views/admin/federation.py index cb05b779e..9c413ec53 100644 --- a/bookwyrm/views/admin/federation.py +++ b/bookwyrm/views/admin/federation.py @@ -60,7 +60,7 @@ class Federation(View): "sort": sort, "software_options": models.FederatedServer.objects.values_list( "application_type", flat=True - ).distinct(), + ).distinct().order_by("application_type"), "form": forms.ServerForm(), } return TemplateResponse(request, "settings/federation/instance_list.html", data) From f68c80dfff0ba6d0223c0d834849156b3f65ee36 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 10:50:17 -0700 Subject: [PATCH 036/167] Adds line length and import-error to .pylintrc --- .pylintrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 7f92d0168..464638853 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,4 +3,7 @@ ignore=migrations load-plugins=pylint.extensions.no_self_use [MESSAGES CONTROL] -disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406,R0401,R0801,C3001 +disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406,R0401,R0801,C3001,import-error + +[FORMAT] +max-line-length=88 From cbb979242d70c363b58a6ab50163024566c01709 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 10:56:18 -0700 Subject: [PATCH 037/167] Revert "Use async requests for broadcasting" --- bookwyrm/models/activitypub_mixin.py | 57 +++++++++++----------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 56f9da208..402cb040b 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -1,5 +1,4 @@ """ activitypub model functionality """ -import asyncio from base64 import b64encode from collections import namedtuple from functools import reduce @@ -7,8 +6,9 @@ import json import operator import logging from uuid import uuid4 +import requests +from requests.exceptions import RequestException -import aiohttp from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 @@ -510,22 +510,15 @@ def broadcast_task(sender_id, activity, recipients): """the celery task for broadcast""" user_model = apps.get_model("bookwyrm.User", require_ready=True) sender = user_model.objects.get(id=sender_id) - asyncio.run(async_broadcast(recipients, sender, activity)) + for recipient in recipients: + try: + sign_and_send(sender, activity, recipient) + except RequestException: + pass -async def async_broadcast(recipients, sender, data): - """Send all the broadcasts simultaneously""" - timeout = aiohttp.ClientTimeout(total=10) - async with aiohttp.ClientSession(timeout=timeout) as session: - tasks = [] - for recipient in recipients: - tasks.append( - asyncio.ensure_future(sign_and_send(session, sender, data, recipient)) - ) - - -async def sign_and_send(session, sender, data, destination): - """Sign the messages and send them in an asynchronous bundle""" +def sign_and_send(sender, data, destination): + """crpyto whatever and http junk""" now = http_date() if not sender.key_pair.private_key: @@ -533,25 +526,21 @@ async def sign_and_send(session, sender, data, destination): raise ValueError("No private key found for sender") digest = make_digest(data) - headers = { - "Date": now, - "Digest": digest, - "Signature": make_signature(sender, destination, now, digest), - "Content-Type": "application/activity+json; charset=utf-8", - "User-Agent": USER_AGENT, - } - try: - async with session.post(destination, data=data, headers=headers) as response: - if not response.ok: - logger.exception( - "Failed to send broadcast to %s: %s", destination, response.reason - ) - return await response - except asyncio.TimeoutError: - logger.info("Connection timed out for url: %s", destination) - except aiohttp.ClientError as err: - logger.exception(err) + response = requests.post( + destination, + data=data, + headers={ + "Date": now, + "Digest": digest, + "Signature": make_signature(sender, destination, now, digest), + "Content-Type": "application/activity+json; charset=utf-8", + "User-Agent": USER_AGENT, + }, + ) + if not response.ok: + response.raise_for_status() + return response # pylint: disable=unused-argument From e0a67f5e18ec5efb594772aee4ff825e5c23044f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 11:06:48 -0700 Subject: [PATCH 038/167] Uses := syntax in user admin view I learned this! It's cool. --- bookwyrm/views/admin/user_admin.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bookwyrm/views/admin/user_admin.py b/bookwyrm/views/admin/user_admin.py index df716d2cb..f1bb87a88 100644 --- a/bookwyrm/views/admin/user_admin.py +++ b/bookwyrm/views/admin/user_admin.py @@ -22,19 +22,16 @@ class UserAdminList(View): def get(self, request, status="local"): """list of users""" filters = {} - server = request.GET.get("server") - if server: + if server := request.GET.get("server"): server = models.FederatedServer.objects.filter(server_name=server).first() filters["federated_server"] = server filters["federated_server__isnull"] = False - username = request.GET.get("username") - if username: + if username := request.GET.get("username"): filters["username__icontains"] = username scope = request.GET.get("scope") if scope and scope == "local": filters["local"] = True - email = request.GET.get("email") - if email: + if email := request.GET.get("email"): filters["email__endswith"] = email filters["local"] = status == "local" From 13e23a868d6180ca28cc02204627c8f89ad19fe2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 11:07:11 -0700 Subject: [PATCH 039/167] Adds instance name filter to federated instance list view This lets you look for a specific server in your (probably very long) instance list. --- .../templates/settings/federation/instance_filters.html | 1 + bookwyrm/views/admin/federation.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/federation/instance_filters.html b/bookwyrm/templates/settings/federation/instance_filters.html index 46ae0c1cf..d6af7e91f 100644 --- a/bookwyrm/templates/settings/federation/instance_filters.html +++ b/bookwyrm/templates/settings/federation/instance_filters.html @@ -2,6 +2,7 @@ {% block filter_fields %} {% include 'settings/federation/software_filter.html' %} +{% include 'settings/users/server_filter.html' %} {% endblock %} diff --git a/bookwyrm/views/admin/federation.py b/bookwyrm/views/admin/federation.py index 9c413ec53..88bd43aac 100644 --- a/bookwyrm/views/admin/federation.py +++ b/bookwyrm/views/admin/federation.py @@ -29,6 +29,8 @@ class Federation(View): filters = {} if software := request.GET.get("application_type"): filters["application_type"] = software + if server := request.GET.get("server"): + filters["server_name"] = server servers = models.FederatedServer.objects.filter(status=status, **filters) @@ -60,7 +62,9 @@ class Federation(View): "sort": sort, "software_options": models.FederatedServer.objects.values_list( "application_type", flat=True - ).distinct().order_by("application_type"), + ) + .distinct() + .order_by("application_type"), "form": forms.ServerForm(), } return TemplateResponse(request, "settings/federation/instance_list.html", data) From 94a6675dc47843f7f7fe049a047d1dc2e9c42a59 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 12:07:22 -0700 Subject: [PATCH 040/167] Pylint fixes --- bookwyrm/importers/calibre_import.py | 2 +- bookwyrm/tests/test_postgres.py | 1 + bookwyrm/utils/isni.py | 2 +- docker-compose.yml | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bookwyrm/importers/calibre_import.py b/bookwyrm/importers/calibre_import.py index 7395e2f7b..5426e9333 100644 --- a/bookwyrm/importers/calibre_import.py +++ b/bookwyrm/importers/calibre_import.py @@ -24,5 +24,5 @@ class CalibreImporter(Importer): super().__init__(*args, **kwargs) def get_shelf(self, normalized_row): - # Calibre export does not indicate which shelf to use. Go with a default one for now + # Calibre export does not indicate which shelf to use. Use a default one for now return Shelf.TO_READ diff --git a/bookwyrm/tests/test_postgres.py b/bookwyrm/tests/test_postgres.py index 624512575..94a8090f4 100644 --- a/bookwyrm/tests/test_postgres.py +++ b/bookwyrm/tests/test_postgres.py @@ -34,6 +34,7 @@ class PostgresTriggers(TestCase): ) book.authors.add(author) book.refresh_from_db() + # pylint: disable=line-too-long self.assertEqual( book.search_vector, "'cool':5B 'goodby':3A 'long':2A 'name':9 'rays':7C 'seri':8 'the':6C 'wow':4B", diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index 180c5e388..ea0364e55 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -106,7 +106,7 @@ def find_authors_by_name(name_string, description=False): if titles: # some of the "titles" in ISNI are a little ...iffy - # '@' is used by ISNI/OCLC to index the starting point ignoring stop words + # @ is used by ISNI/OCLC to index the starting point ignoring stop words # (e.g. "The @Government of no one") title_elements = [ e diff --git a/docker-compose.yml b/docker-compose.yml index c5ff1f21b..c654374b9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: command: celery -A celerywyrm flower --basic_auth=${FLOWER_USER}:${FLOWER_PASSWORD} env_file: .env ports: - - ${FLOWER_PORT} + - ${FLOWER_PORT}:${FLOWER_PORT} volumes: - .:/app networks: From 3ad0a5d07357d60597667605ec12e43f7606b90a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 13:06:29 -0700 Subject: [PATCH 041/167] Use update_fields to limit `remove_list_task`s If we know what fields were updated, we can avoid running this task. This also adds some mocks where they are needed for the list view. --- bookwyrm/lists_stream.py | 17 +++++++++++------ bookwyrm/models/list.py | 4 ++-- bookwyrm/tests/views/lists/test_curate.py | 4 +++- bookwyrm/tests/views/lists/test_embed.py | 4 +++- bookwyrm/tests/views/lists/test_list.py | 14 ++++++++------ bookwyrm/tests/views/lists/test_list_item.py | 4 +++- bookwyrm/tests/views/lists/test_lists.py | 18 +++++++++++++----- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index c40d2b534..0977ad8c2 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -114,15 +114,20 @@ class ListsStream(RedisStore): @receiver(signals.post_save, sender=models.List) # pylint: disable=unused-argument -def add_list_on_create(sender, instance, created, *args, **kwargs): +def add_list_on_create(sender, instance, created, *args, update_fields=None, **kwargs): """add newly created lists streams""" - if not created: - # the privacy may have changed, so we need to re-do the whole thing - remove_list_task.delay(instance.id, re_add=True) + if created: + # when creating new things, gotta wait on the transaction + transaction.on_commit(lambda: add_list_on_create_command(instance.id)) return - # when creating new things, gotta wait on the transaction - transaction.on_commit(lambda: add_list_on_create_command(instance.id)) + # if update_fields was specified, we can check if privacy was updated, but if + # it wasn't specified (ie, by an activitypub update), there's no way to know + if update_fields and "privacy" not in update_fields: + return + + # the privacy may have changed, so we need to re-do the whole thing + remove_list_task.delay(instance.id, re_add=True) @receiver(signals.post_delete, sender=models.List) diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index ea524cc54..0195020e0 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -129,7 +129,7 @@ class List(OrderedCollectionMixin, BookWyrmModel): """on save, update embed_key and avoid clash with existing code""" if not self.embed_key: self.embed_key = uuid.uuid4() - return super().save(*args, **kwargs) + super().save(*args, **kwargs) class ListItem(CollectionItemMixin, BookWyrmModel): @@ -156,7 +156,7 @@ class ListItem(CollectionItemMixin, BookWyrmModel): super().save(*args, **kwargs) # tick the updated date on the parent list self.book_list.updated_date = timezone.now() - self.book_list.save(broadcast=False) + self.book_list.save(broadcast=False, update_fields=["updated_date"]) list_owner = self.book_list.user model = apps.get_model("bookwyrm.Notification", require_ready=True) diff --git a/bookwyrm/tests/views/lists/test_curate.py b/bookwyrm/tests/views/lists/test_curate.py index 9be8c2a15..9f3427b2c 100644 --- a/bookwyrm/tests/views/lists/test_curate.py +++ b/bookwyrm/tests/views/lists/test_curate.py @@ -36,7 +36,9 @@ class ListViews(TestCase): parent_work=work, ) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user ) diff --git a/bookwyrm/tests/views/lists/test_embed.py b/bookwyrm/tests/views/lists/test_embed.py index dc61736d3..4191ffe0d 100644 --- a/bookwyrm/tests/views/lists/test_embed.py +++ b/bookwyrm/tests/views/lists/test_embed.py @@ -36,7 +36,9 @@ class ListViews(TestCase): parent_work=work, ) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user ) diff --git a/bookwyrm/tests/views/lists/test_list.py b/bookwyrm/tests/views/lists/test_list.py index bcec0822f..98b0a461a 100644 --- a/bookwyrm/tests/views/lists/test_list.py +++ b/bookwyrm/tests/views/lists/test_list.py @@ -65,7 +65,9 @@ class ListViews(TestCase): parent_work=work_four, ) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user ) @@ -244,7 +246,7 @@ class ListViews(TestCase): with patch( "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" - ) as mock: + ) as mock, patch("bookwyrm.lists_stream.remove_list_task.delay"): result = view(request, self.list.id) self.assertEqual(mock.call_count, 1) @@ -596,7 +598,7 @@ class ListViews(TestCase): def test_add_book_outsider(self): """put a book on a list""" self.list.curation = "open" - self.list.save(broadcast=False) + self.list.save(broadcast=False, update_fields=["curation"]) request = self.factory.post( "", { @@ -625,7 +627,7 @@ class ListViews(TestCase): def test_add_book_pending(self): """put a book on a list awaiting approval""" self.list.curation = "curated" - self.list.save(broadcast=False) + self.list.save(broadcast=False, update_fields=["curation"]) request = self.factory.post( "", { @@ -658,7 +660,7 @@ class ListViews(TestCase): def test_add_book_self_curated(self): """put a book on a list automatically approved""" self.list.curation = "curated" - self.list.save(broadcast=False) + self.list.save(broadcast=False, update_fields=["curation"]) request = self.factory.post( "", { @@ -687,7 +689,7 @@ class ListViews(TestCase): def test_add_book_permission_denied(self): """you can't add to that list""" self.list.curation = "closed" - self.list.save(broadcast=False) + self.list.save(broadcast=False, update_fields=["curation"]) request = self.factory.post( "", { diff --git a/bookwyrm/tests/views/lists/test_list_item.py b/bookwyrm/tests/views/lists/test_list_item.py index 50be3c286..b95282bef 100644 --- a/bookwyrm/tests/views/lists/test_list_item.py +++ b/bookwyrm/tests/views/lists/test_list_item.py @@ -32,7 +32,9 @@ class ListItemViews(TestCase): remote_id="https://example.com/book/1", parent_work=work, ) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user ) diff --git a/bookwyrm/tests/views/lists/test_lists.py b/bookwyrm/tests/views/lists/test_lists.py index f65d2e4c2..c2263b933 100644 --- a/bookwyrm/tests/views/lists/test_lists.py +++ b/bookwyrm/tests/views/lists/test_lists.py @@ -39,7 +39,9 @@ class ListViews(TestCase): view = views.Lists.as_view() with patch( "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" - ), patch("bookwyrm.lists_stream.add_list_task.delay"): + ), patch("bookwyrm.lists_stream.add_list_task.delay"), patch( + "bookwyrm.lists_stream.remove_list_task.delay" + ): models.List.objects.create(name="Public list", user=self.local_user) models.List.objects.create( name="Private list", privacy="direct", user=self.local_user @@ -62,7 +64,9 @@ class ListViews(TestCase): def test_saved_lists_page(self): """there are so many views, this just makes sure it LOADS""" view = views.SavedLists.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): booklist = models.List.objects.create( name="Public list", user=self.local_user ) @@ -82,7 +86,9 @@ class ListViews(TestCase): def test_saved_lists_page_empty(self): """there are so many views, this just makes sure it LOADS""" view = views.SavedLists.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): models.List.objects.create(name="Public list", user=self.local_user) models.List.objects.create( name="Private list", privacy="direct", user=self.local_user @@ -108,7 +114,9 @@ class ListViews(TestCase): def test_user_lists_page(self): """there are so many views, this just makes sure it LOADS""" view = views.UserLists.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): models.List.objects.create(name="Public list", user=self.local_user) models.List.objects.create( name="Private list", privacy="direct", user=self.local_user @@ -146,7 +154,7 @@ class ListViews(TestCase): request.user = self.local_user with patch( "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" - ) as mock: + ) as mock, patch("bookwyrm.lists_stream.remove_list_task.delay"): result = view(request) self.assertEqual(mock.call_count, 1) From 495bf203b073bc0bf8c7538ae74fc4ce239f1e74 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 13:45:53 -0700 Subject: [PATCH 042/167] Mocks inbox and search tests --- bookwyrm/tests/views/inbox/test_inbox_remove.py | 4 +++- bookwyrm/tests/views/inbox/test_inbox_update.py | 7 +++++-- bookwyrm/tests/views/test_search.py | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_remove.py b/bookwyrm/tests/views/inbox/test_inbox_remove.py index 53288e0d3..d7b3f6778 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_remove.py +++ b/bookwyrm/tests/views/inbox/test_inbox_remove.py @@ -75,7 +75,9 @@ class InboxRemove(TestCase): def test_handle_remove_book_from_list(self): """listing a book""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): booklist = models.List.objects.create( name="test list", user=self.local_user, diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py index 18b2e5d59..e8593c2be 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_update.py +++ b/bookwyrm/tests/views/inbox/test_inbox_update.py @@ -50,7 +50,9 @@ class InboxUpdate(TestCase): def test_update_list(self): """a new list""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="hi", remote_id="https://example.com/list/22", user=self.local_user ) @@ -69,7 +71,8 @@ class InboxUpdate(TestCase): "curation": "curated", "@context": "https://www.w3.org/ns/activitystreams", } - views.inbox.activity_task(activity) + with patch("bookwyrm.lists_stream.remove_list_task.delay"): + views.inbox.activity_task(activity) book_list.refresh_from_db() self.assertEqual(book_list.name, "Test List") self.assertEqual(book_list.curation, "curated") diff --git a/bookwyrm/tests/views/test_search.py b/bookwyrm/tests/views/test_search.py index 51166f2fa..d6e00edb6 100644 --- a/bookwyrm/tests/views/test_search.py +++ b/bookwyrm/tests/views/test_search.py @@ -140,7 +140,9 @@ class Views(TestCase): def test_search_lists(self): """searches remote connectors""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): booklist = models.List.objects.create( user=self.local_user, name="test list" ) From 46421f9672d73d8414d638cac391faa90b3c698a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 13:48:15 -0700 Subject: [PATCH 043/167] Mocks for lists model --- bookwyrm/tests/models/test_list.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bookwyrm/tests/models/test_list.py b/bookwyrm/tests/models/test_list.py index e4ecfe897..de6957b57 100644 --- a/bookwyrm/tests/models/test_list.py +++ b/bookwyrm/tests/models/test_list.py @@ -23,7 +23,9 @@ class List(TestCase): def test_remote_id(self, _): """shelves use custom remote ids""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="Test List", user=self.local_user ) @@ -32,7 +34,9 @@ class List(TestCase): def test_to_activity(self, _): """jsonify it""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="Test List", user=self.local_user ) @@ -46,7 +50,9 @@ class List(TestCase): def test_list_item(self, _): """a list entry""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="Test List", user=self.local_user, privacy="unlisted" ) @@ -64,7 +70,9 @@ class List(TestCase): def test_list_item_pending(self, _): """a list entry""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="Test List", user=self.local_user ) @@ -84,7 +92,9 @@ class List(TestCase): def test_embed_key(self, _): """embed_key should never be empty""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): book_list = models.List.objects.create( name="Test List", user=self.local_user ) From 6e70ceb094ed5ea0139b8ac7d689e476eca3350f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 19:43:59 -0700 Subject: [PATCH 044/167] More mocks --- bookwyrm/tests/lists_stream/test_signals.py | 14 ++++++++------ bookwyrm/tests/lists_stream/test_stream.py | 1 + bookwyrm/tests/lists_stream/test_tasks.py | 4 +++- bookwyrm/tests/models/test_group.py | 9 ++++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bookwyrm/tests/lists_stream/test_signals.py b/bookwyrm/tests/lists_stream/test_signals.py index f82dba3a4..96f1ae231 100644 --- a/bookwyrm/tests/lists_stream/test_signals.py +++ b/bookwyrm/tests/lists_stream/test_signals.py @@ -32,9 +32,10 @@ class ListsStreamSignals(TestCase): def test_add_list_on_create_command(self, _): """a new lists has entered""" - book_list = models.List.objects.create( - user=self.remote_user, name="hi", privacy="public" - ) + with patch("bookwyrm.lists_stream.remove_list_task.delay"): + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) with patch("bookwyrm.lists_stream.add_list_task.delay") as mock: lists_stream.add_list_on_create_command(book_list.id) self.assertEqual(mock.call_count, 1) @@ -43,9 +44,10 @@ class ListsStreamSignals(TestCase): def test_remove_list_on_delete(self, _): """delete a list""" - book_list = models.List.objects.create( - user=self.remote_user, name="hi", privacy="public" - ) + with patch("bookwyrm.lists_stream.remove_list_task.delay"): + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) with patch("bookwyrm.lists_stream.remove_list_task.delay") as mock: lists_stream.remove_list_on_delete(models.List, book_list) args = mock.call_args[0] diff --git a/bookwyrm/tests/lists_stream/test_stream.py b/bookwyrm/tests/lists_stream/test_stream.py index 4d8aa52b2..0e87c7436 100644 --- a/bookwyrm/tests/lists_stream/test_stream.py +++ b/bookwyrm/tests/lists_stream/test_stream.py @@ -11,6 +11,7 @@ from bookwyrm import lists_stream, models @patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.remove_list_task.delay") class ListsStream(TestCase): """using redis to build activity streams""" diff --git a/bookwyrm/tests/lists_stream/test_tasks.py b/bookwyrm/tests/lists_stream/test_tasks.py index 1da36b71b..55c5d98c8 100644 --- a/bookwyrm/tests/lists_stream/test_tasks.py +++ b/bookwyrm/tests/lists_stream/test_tasks.py @@ -35,7 +35,9 @@ class Activitystreams(TestCase): inbox="https://example.com/users/rat/inbox", outbox="https://example.com/users/rat/outbox", ) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): self.list = models.List.objects.create( user=self.local_user, name="hi", privacy="public" ) diff --git a/bookwyrm/tests/models/test_group.py b/bookwyrm/tests/models/test_group.py index 8739f7fee..86cafaa39 100644 --- a/bookwyrm/tests/models/test_group.py +++ b/bookwyrm/tests/models/test_group.py @@ -80,7 +80,9 @@ class Group(TestCase): """follower-only group booklists should not be excluded from group booklist listing for group members who do not follower list owner""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): followers_list = models.List.objects.create( name="Followers List", curation="group", @@ -101,8 +103,9 @@ class Group(TestCase): """private group booklists should not be excluded from group booklist listing for group members""" - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): - + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.remove_list_task.delay"): private_list = models.List.objects.create( name="Private List", privacy="direct", From 516c4a9790f1142d2baa4ef641f5a0fc680de07b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 21:02:44 -0700 Subject: [PATCH 045/167] Add warning to dashboard if email sender looks misconfigured This can be a really obscure error, hopefully this warning will catch potential issues. --- bookwyrm/templates/settings/dashboard/dashboard.html | 11 +++++++++++ bookwyrm/views/admin/dashboard.py | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html index cec3e89ac..46d552fb1 100644 --- a/bookwyrm/templates/settings/dashboard/dashboard.html +++ b/bookwyrm/templates/settings/dashboard/dashboard.html @@ -37,6 +37,17 @@
+ {% if email_config_error %} +
+ + {% blocktrans trimmed %} + Your outgoing email address, {{ email_sender }}, may be misconfigured. + {% endblocktrans %} + {% trans "Check the EMAIL_SENDER_NAME and EMAIL_SENDER_DOMAIN in your .env." %} + +
+ {% endif %} + {% if reports %}
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py index b06b6ba00..8b9017bb4 100644 --- a/bookwyrm/views/admin/dashboard.py +++ b/bookwyrm/views/admin/dashboard.py @@ -1,5 +1,7 @@ """ instance overview """ from datetime import timedelta +import re + from dateutil.parser import parse from packaging import version @@ -13,6 +15,7 @@ from django.views import View from bookwyrm import models, settings from bookwyrm.connectors.abstract_connector import get_data from bookwyrm.connectors.connector_manager import ConnectorException +from bookwyrm.utils import regex # pylint: disable= no-self-use @@ -88,6 +91,10 @@ class Dashboard(View): }, ) + email_config_error = re.findall( + r"[\s\@]", settings.EMAIL_SENDER_DOMAIN + ) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN) + data = { "start": start.strftime("%Y-%m-%d"), "end": end.strftime("%Y-%m-%d"), @@ -109,6 +116,8 @@ class Dashboard(View): "status_stats": status_chart.get_chart(start, end, interval), "register_stats": register_chart.get_chart(start, end, interval), "works_stats": works_chart.get_chart(start, end, interval), + "email_config_error": email_config_error, + "email_sender": f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}", } # check version From e16506c1dfbc570172810c668f65716542106bf8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 21:25:07 -0700 Subject: [PATCH 046/167] Fixes logic error in checking relationships I had the logic backwards for pending relationships. --- bookwyrm/models/relationship.py | 4 ++-- bookwyrm/templatetags/interaction.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py index 171f45840..313200514 100644 --- a/bookwyrm/models/relationship.py +++ b/bookwyrm/models/relationship.py @@ -218,7 +218,7 @@ def clear_cache(user_subject, user_object): """clear relationship cache""" cache.delete_many( [ - f"relationship-{user_subject.id}-{user_object.id}", - f"relationship-{user_object.id}-{user_subject.id}", + f"cached-relationship-{user_subject.id}-{user_object.id}", + f"cached-relationship-{user_object.id}-{user_subject.id}", ] ) diff --git a/bookwyrm/templatetags/interaction.py b/bookwyrm/templatetags/interaction.py index 89a25420a..40f92dcd6 100644 --- a/bookwyrm/templatetags/interaction.py +++ b/bookwyrm/templatetags/interaction.py @@ -42,7 +42,7 @@ def get_relationship(context, user_object): """caches the relationship between the logged in user and another user""" user = context["request"].user return get_or_set( - f"relationship-{user.id}-{user_object.id}", + f"cached-relationship-{user.id}-{user_object.id}", get_relationship_name, user, user_object, @@ -61,6 +61,6 @@ def get_relationship_name(user, user_object): types["is_blocked"] = True elif user_object in user.following.all(): types["is_following"] = True - elif user_object in user.follower_requests.all(): + elif user in user_object.follower_requests.all(): types["is_follow_pending"] = True return types From 89165fd909ba4f4033f706569d77b2fd5348c8e8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 3 Jul 2022 08:28:24 -0700 Subject: [PATCH 047/167] Creates helper function for creating charts --- bookwyrm/views/admin/dashboard.py | 177 ++++++++++++++++-------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py index 8b9017bb4..df34fe5bf 100644 --- a/bookwyrm/views/admin/dashboard.py +++ b/bookwyrm/views/admin/dashboard.py @@ -29,96 +29,18 @@ class Dashboard(View): def get(self, request): """list of users""" - interval = int(request.GET.get("days", 1)) - now = timezone.now() - start = request.GET.get("start") - if start: - start = timezone.make_aware(parse(start)) - else: - start = now - timedelta(days=6 * interval) - - end = request.GET.get("end") - end = timezone.make_aware(parse(end)) if end else now - start = start.replace(hour=0, minute=0, second=0) - - user_queryset = models.User.objects.filter(local=True) - user_chart = Chart( - queryset=user_queryset, - queries={ - "total": lambda q, s, e: q.filter( - Q(is_active=True) | Q(deactivation_date__gt=e), - created_date__lte=e, - ).count(), - "active": lambda q, s, e: q.filter( - Q(is_active=True) | Q(deactivation_date__gt=e), - created_date__lte=e, - ) - .filter( - last_active_date__gt=e - timedelta(days=31), - ) - .count(), - }, - ) - - status_queryset = models.Status.objects.filter(user__local=True, deleted=False) - status_chart = Chart( - queryset=status_queryset, - queries={ - "total": lambda q, s, e: q.filter( - created_date__gt=s, - created_date__lte=e, - ).count() - }, - ) - - register_chart = Chart( - queryset=user_queryset, - queries={ - "total": lambda q, s, e: q.filter( - created_date__gt=s, - created_date__lte=e, - ).count() - }, - ) - - works_chart = Chart( - queryset=models.Work.objects, - queries={ - "total": lambda q, s, e: q.filter( - created_date__gt=s, - created_date__lte=e, - ).count() - }, - ) + data = get_charts_and_stats(request) + # Make sure email looks properly configured email_config_error = re.findall( r"[\s\@]", settings.EMAIL_SENDER_DOMAIN ) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN) - data = { - "start": start.strftime("%Y-%m-%d"), - "end": end.strftime("%Y-%m-%d"), - "interval": interval, - "users": user_queryset.filter(is_active=True).count(), - "active_users": user_queryset.filter( - is_active=True, last_active_date__gte=now - timedelta(days=31) - ).count(), - "statuses": status_queryset.count(), - "works": models.Work.objects.count(), - "reports": models.Report.objects.filter(resolved=False).count(), - "pending_domains": models.LinkDomain.objects.filter( - status="pending" - ).count(), - "invite_requests": models.InviteRequest.objects.filter( - ignored=False, invite__isnull=True - ).count(), - "user_stats": user_chart.get_chart(start, end, interval), - "status_stats": status_chart.get_chart(start, end, interval), - "register_stats": register_chart.get_chart(start, end, interval), - "works_stats": works_chart.get_chart(start, end, interval), - "email_config_error": email_config_error, - "email_sender": f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}", - } + data["email_config_error"] = email_config_error + # pylint: disable=line-too-long + data[ + "email_sender" + ] = f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}" # check version try: @@ -135,6 +57,91 @@ class Dashboard(View): return TemplateResponse(request, "settings/dashboard/dashboard.html", data) +def get_charts_and_stats(request): + """Defines the dashbaord charts""" + interval = int(request.GET.get("days", 1)) + now = timezone.now() + start = request.GET.get("start") + if start: + start = timezone.make_aware(parse(start)) + else: + start = now - timedelta(days=6 * interval) + + end = request.GET.get("end") + end = timezone.make_aware(parse(end)) if end else now + start = start.replace(hour=0, minute=0, second=0) + + user_queryset = models.User.objects.filter(local=True) + user_chart = Chart( + queryset=user_queryset, + queries={ + "total": lambda q, s, e: q.filter( + Q(is_active=True) | Q(deactivation_date__gt=e), + created_date__lte=e, + ).count(), + "active": lambda q, s, e: q.filter( + Q(is_active=True) | Q(deactivation_date__gt=e), + created_date__lte=e, + ) + .filter( + last_active_date__gt=e - timedelta(days=31), + ) + .count(), + }, + ) + + status_queryset = models.Status.objects.filter(user__local=True, deleted=False) + status_chart = Chart( + queryset=status_queryset, + queries={ + "total": lambda q, s, e: q.filter( + created_date__gt=s, + created_date__lte=e, + ).count() + }, + ) + + register_chart = Chart( + queryset=user_queryset, + queries={ + "total": lambda q, s, e: q.filter( + created_date__gt=s, + created_date__lte=e, + ).count() + }, + ) + + works_chart = Chart( + queryset=models.Work.objects, + queries={ + "total": lambda q, s, e: q.filter( + created_date__gt=s, + created_date__lte=e, + ).count() + }, + ) + return { + "start": start.strftime("%Y-%m-%d"), + "end": end.strftime("%Y-%m-%d"), + "interval": interval, + "users": user_queryset.filter(is_active=True).count(), + "active_users": user_queryset.filter( + is_active=True, last_active_date__gte=now - timedelta(days=31) + ).count(), + "statuses": status_queryset.count(), + "works": models.Work.objects.count(), + "reports": models.Report.objects.filter(resolved=False).count(), + "pending_domains": models.LinkDomain.objects.filter(status="pending").count(), + "invite_requests": models.InviteRequest.objects.filter( + ignored=False, invite__isnull=True + ).count(), + "user_stats": user_chart.get_chart(start, end, interval), + "status_stats": status_chart.get_chart(start, end, interval), + "register_stats": register_chart.get_chart(start, end, interval), + "works_stats": works_chart.get_chart(start, end, interval), + } + + class Chart: """Data for a chart""" From 5d363da175faa8289d94e51778af281add117178 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 3 Jul 2022 11:05:20 -0700 Subject: [PATCH 048/167] Handle getting edition data as dict or string --- bookwyrm/connectors/inventaire.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index 3d5f913bd..df9b2e43a 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -160,12 +160,13 @@ class Connector(AbstractConnector): def create_edition_from_data(self, work, edition_data, instance=None): """pass in the url as data and then call the version in abstract connector""" - try: - data = self.get_book_data(edition_data) - except ConnectorException: - # who, indeed, knows - return - super().create_edition_from_data(work, data, instance=instance) + if isinstance(edition_data, str): + try: + edition_data = self.get_book_data(edition_data) + except ConnectorException: + # who, indeed, knows + return + super().create_edition_from_data(work, edition_data, instance=instance) def get_cover_url(self, cover_blob, *_): """format the relative cover url into an absolute one: From 7f78140015d6e2c9bac86ba9931911009c407dba Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 13:14:22 -0700 Subject: [PATCH 049/167] Uses library for html cleanup --- bookwyrm/models/fields.py | 6 +-- bookwyrm/sanitize_html.py | 71 ---------------------------- bookwyrm/tests/test_sanitize_html.py | 36 ++++++-------- bookwyrm/utils/sanitizer.py | 25 ++++++++++ bookwyrm/views/status.py | 7 +-- requirements.txt | 1 + 6 files changed, 44 insertions(+), 102 deletions(-) delete mode 100644 bookwyrm/sanitize_html.py create mode 100644 bookwyrm/utils/sanitizer.py diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 62c61cc40..785f3397c 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -16,7 +16,7 @@ from django.utils.encoding import filepath_to_uri from bookwyrm import activitypub from bookwyrm.connectors import get_image -from bookwyrm.sanitize_html import InputHtmlParser +from bookwyrm.utils.sanitizer import clean from bookwyrm.settings import MEDIA_FULL_URL @@ -497,9 +497,7 @@ class HtmlField(ActivitypubFieldMixin, models.TextField): def field_from_activity(self, value): if not value or value == MISSING: return None - sanitizer = InputHtmlParser() - sanitizer.feed(value) - return sanitizer.get_output() + return clean(value) class ArrayField(ActivitypubFieldMixin, DjangoArrayField): diff --git a/bookwyrm/sanitize_html.py b/bookwyrm/sanitize_html.py deleted file mode 100644 index 4edd2818e..000000000 --- a/bookwyrm/sanitize_html.py +++ /dev/null @@ -1,71 +0,0 @@ -""" html parser to clean up incoming text from unknown sources """ -from html.parser import HTMLParser - - -class InputHtmlParser(HTMLParser): # pylint: disable=abstract-method - """Removes any html that isn't allowed_tagsed from a block""" - - def __init__(self): - HTMLParser.__init__(self) - self.allowed_tags = [ - "p", - "blockquote", - "br", - "b", - "i", - "strong", - "em", - "pre", - "a", - "span", - "ul", - "ol", - "li", - ] - self.allowed_attrs = ["href", "rel", "src", "alt"] - self.tag_stack = [] - self.output = [] - # if the html appears invalid, we just won't allow any at all - self.allow_html = True - - def handle_starttag(self, tag, attrs): - """check if the tag is valid""" - if self.allow_html and tag in self.allowed_tags: - allowed_attrs = " ".join( - f'{a}="{v}"' for a, v in attrs if a in self.allowed_attrs - ) - reconstructed = f"<{tag}" - if allowed_attrs: - reconstructed += " " + allowed_attrs - reconstructed += ">" - self.output.append(("tag", reconstructed)) - self.tag_stack.append(tag) - else: - self.output.append(("data", "")) - - def handle_endtag(self, tag): - """keep the close tag""" - if not self.allow_html or tag not in self.allowed_tags: - self.output.append(("data", "")) - return - - if not self.tag_stack or self.tag_stack[-1] != tag: - # the end tag doesn't match the most recent start tag - self.allow_html = False - self.output.append(("data", "")) - return - - self.tag_stack = self.tag_stack[:-1] - self.output.append(("tag", f"")) - - def handle_data(self, data): - """extract the answer, if we're in an answer tag""" - self.output.append(("data", data)) - - def get_output(self): - """convert the output from a list of tuples to a string""" - if self.tag_stack: - self.allow_html = False - if not self.allow_html: - return "".join(v for (k, v) in self.output if k == "data") - return "".join(v for (k, v) in self.output) diff --git a/bookwyrm/tests/test_sanitize_html.py b/bookwyrm/tests/test_sanitize_html.py index 5814f2207..ecdd69793 100644 --- a/bookwyrm/tests/test_sanitize_html.py +++ b/bookwyrm/tests/test_sanitize_html.py @@ -1,7 +1,7 @@ """ make sure only valid html gets to the app """ from django.test import TestCase -from bookwyrm.sanitize_html import InputHtmlParser +from bookwyrm.utils.sanitizer import clean class Sanitizer(TestCase): @@ -10,53 +10,45 @@ class Sanitizer(TestCase): def test_no_html(self): """just text""" input_text = "no html " - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual(input_text, output) def test_valid_html(self): """leave the html untouched""" input_text = "yes html" - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual(input_text, output) def test_valid_html_attrs(self): """and don't remove useful attributes""" input_text = 'yes html' - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual(input_text, output) def test_valid_html_invalid_attrs(self): """do remove un-approved attributes""" input_text = 'yes html' - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual(output, 'yes html') def test_invalid_html(self): """remove all html when the html is malformed""" input_text = "yes html" - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual("yes html", output) input_text = "yes html " - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual("yes html ", output) def test_disallowed_html(self): """remove disallowed html but keep allowed html""" input_text = "
yes html
" - parser = InputHtmlParser() - parser.feed(input_text) - output = parser.get_output() + output = clean(input_text) self.assertEqual(" yes html", output) + + def test_escaped_bracket(self): + """remove > and <""" + input_text = "<dev>hi</div>" + output = clean(input_text) + self.assertEqual("hi", output) diff --git a/bookwyrm/utils/sanitizer.py b/bookwyrm/utils/sanitizer.py new file mode 100644 index 000000000..676921949 --- /dev/null +++ b/bookwyrm/utils/sanitizer.py @@ -0,0 +1,25 @@ +"""Clean user-provided text""" +import bleach + + +def clean(input_text): + """Run through "bleach" """ + return bleach.clean( + input_text, + tags=[ + "p", + "blockquote", + "br", + "b", + "i", + "strong", + "em", + "pre", + "a", + "span", + "ul", + "ol", + "li", + ], + attributes=["href", "rel", "src", "alt"], + ) diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 670ea5717..0dd9e0f80 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -16,9 +16,8 @@ from django.views.decorators.http import require_POST from markdown import markdown from bookwyrm import forms, models -from bookwyrm.sanitize_html import InputHtmlParser from bookwyrm.settings import DOMAIN -from bookwyrm.utils import regex +from bookwyrm.utils import regex, sanitizer from .helpers import handle_remote_webfinger, is_api_request from .helpers import load_date_in_user_tz_as_utc @@ -268,6 +267,4 @@ def to_markdown(content): content = format_links(content) content = markdown(content) # sanitize resulting html - sanitizer = InputHtmlParser() - sanitizer.feed(content) - return sanitizer.get_output() + return sanitizer.clean(content) diff --git a/requirements.txt b/requirements.txt index 0155782cc..3d9f686ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ aiohttp==3.8.1 +bleach==5.0.1 celery==5.2.2 colorthief==0.2.1 Django==3.2.13 From 62aa4bf869625186e0c7f24d259cfb2caac6f4d3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 13:21:18 -0700 Subject: [PATCH 050/167] Tick version number --- bookwyrm/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index dc0d71f30..e67fb5e1e 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _ env = Env() env.read_env() DOMAIN = env("DOMAIN") -VERSION = "0.4.0" +VERSION = "0.4.1" RELEASE_API = env( "RELEASE_API", From 13376f89708fea095d97fdeed6950da701aa52d9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 13:24:13 -0700 Subject: [PATCH 051/167] Catches missing reference to previous sanitizer --- bookwyrm/status.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bookwyrm/status.py b/bookwyrm/status.py index 09fbdc06e..de7682ee7 100644 --- a/bookwyrm/status.py +++ b/bookwyrm/status.py @@ -2,15 +2,13 @@ from django.db import transaction from bookwyrm import models -from bookwyrm.sanitize_html import InputHtmlParser +from bookwyrm.utils import sanitizer def create_generated_note(user, content, mention_books=None, privacy="public"): """a note created by the app about user activity""" # sanitize input html - parser = InputHtmlParser() - parser.feed(content) - content = parser.get_output() + content = sanitizer.clean(content) with transaction.atomic(): # create but don't save From 70beb24d95657d5186d73d71599088046dd5e891 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 13:34:09 -0700 Subject: [PATCH 052/167] Removed misleading test This wasn't really testing what I wanted it to. --- bookwyrm/tests/test_sanitize_html.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bookwyrm/tests/test_sanitize_html.py b/bookwyrm/tests/test_sanitize_html.py index ecdd69793..ca1643e8f 100644 --- a/bookwyrm/tests/test_sanitize_html.py +++ b/bookwyrm/tests/test_sanitize_html.py @@ -46,9 +46,3 @@ class Sanitizer(TestCase): input_text = "
yes html
" output = clean(input_text) self.assertEqual(" yes html", output) - - def test_escaped_bracket(self): - """remove > and <""" - input_text = "<dev>hi</div>" - output = clean(input_text) - self.assertEqual("hi", output) From 9d9b7f366a2b6b711c5b6f3609286a26f98486de Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 13:45:28 -0700 Subject: [PATCH 053/167] Use "strip" in bleach This removes forbidden html, rather than leaving them in place but unrendered. --- bookwyrm/tests/test_sanitize_html.py | 6 +++--- bookwyrm/utils/sanitizer.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/test_sanitize_html.py b/bookwyrm/tests/test_sanitize_html.py index ca1643e8f..449acdafb 100644 --- a/bookwyrm/tests/test_sanitize_html.py +++ b/bookwyrm/tests/test_sanitize_html.py @@ -32,14 +32,14 @@ class Sanitizer(TestCase): self.assertEqual(output, 'yes html') def test_invalid_html(self): - """remove all html when the html is malformed""" + """don't allow malformed html""" input_text = "yes html" output = clean(input_text) - self.assertEqual("yes html", output) + self.assertEqual("yes html", output) input_text = "yes html " output = clean(input_text) - self.assertEqual("yes html ", output) + self.assertEqual("yes html ", output) def test_disallowed_html(self): """remove disallowed html but keep allowed html""" diff --git a/bookwyrm/utils/sanitizer.py b/bookwyrm/utils/sanitizer.py index 676921949..f6c87358c 100644 --- a/bookwyrm/utils/sanitizer.py +++ b/bookwyrm/utils/sanitizer.py @@ -22,4 +22,5 @@ def clean(input_text): "li", ], attributes=["href", "rel", "src", "alt"], + strip=True, ) From 5672c73ac420d152858aa57a8e1a2cf132bc0086 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jul 2022 17:32:55 -0700 Subject: [PATCH 054/167] Show deleted users as red in the user list It can be hard to differentiate at a glance if a user is deleted or suspended -- without this, you would have to read the deactivation reason. By making deletions (moderator and self deletions) red, it's clear at a glance if an account has been permanently deleted or just temporarily suspended. --- bookwyrm/templates/settings/users/user_admin.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bookwyrm/templates/settings/users/user_admin.html b/bookwyrm/templates/settings/users/user_admin.html index 4144f0bde..059e064db 100644 --- a/bookwyrm/templates/settings/users/user_admin.html +++ b/bookwyrm/templates/settings/users/user_admin.html @@ -72,6 +72,12 @@ {% trans "Active" %} + {% elif user.deactivation_reason == "moderator_deletion" or user.deactivation_reason == "self_deletion" %} + + {% trans "Deleted" %} + ({{ user.get_deactivation_reason_display }}) {% else %}