From fdf5113143fa3ac9fac806f5547e0a03b8c63e3b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 8 Apr 2021 16:00:57 -0700 Subject: [PATCH 001/109] Removes tag code --- bookwyrm/models/__init__.py | 2 - bookwyrm/models/tag.py | 63 ---------------- bookwyrm/tests/views/test_tag.py | 119 ------------------------------- bookwyrm/urls.py | 5 -- bookwyrm/views/__init__.py | 1 - bookwyrm/views/tag.py | 73 ------------------- 6 files changed, 263 deletions(-) delete mode 100644 bookwyrm/models/tag.py delete mode 100644 bookwyrm/tests/views/test_tag.py delete mode 100644 bookwyrm/views/tag.py diff --git a/bookwyrm/models/__init__.py b/bookwyrm/models/__init__.py index 35e32c2cf..2a25a5251 100644 --- a/bookwyrm/models/__init__.py +++ b/bookwyrm/models/__init__.py @@ -17,8 +17,6 @@ from .favorite import Favorite from .notification import Notification from .readthrough import ReadThrough, ProgressUpdate, ProgressMode -from .tag import Tag, UserTag - from .user import User, KeyPair, AnnualGoal from .relationship import UserFollows, UserFollowRequest, UserBlocks from .report import Report, ReportComment diff --git a/bookwyrm/models/tag.py b/bookwyrm/models/tag.py deleted file mode 100644 index 2c45b8f91..000000000 --- a/bookwyrm/models/tag.py +++ /dev/null @@ -1,63 +0,0 @@ -""" models for storing different kinds of Activities """ -import urllib.parse - -from django.apps import apps -from django.db import models - -from bookwyrm import activitypub -from bookwyrm.settings import DOMAIN -from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin -from .base_model import BookWyrmModel -from . import fields - - -class Tag(OrderedCollectionMixin, BookWyrmModel): - """ freeform tags for books """ - - name = fields.CharField(max_length=100, unique=True) - identifier = models.CharField(max_length=100) - - @property - def books(self): - """ count of books associated with this tag """ - edition_model = apps.get_model("bookwyrm.Edition", require_ready=True) - return ( - edition_model.objects.filter(usertag__tag__identifier=self.identifier) - .order_by("-created_date") - .distinct() - ) - - collection_queryset = books - - def get_remote_id(self): - """ tag should use identifier not id in remote_id """ - base_path = "https://%s" % DOMAIN - return "%s/tag/%s" % (base_path, self.identifier) - - def save(self, *args, **kwargs): - """ create a url-safe lookup key for the tag """ - if not self.id: - # add identifiers to new tags - self.identifier = urllib.parse.quote_plus(self.name) - super().save(*args, **kwargs) - - -class UserTag(CollectionItemMixin, BookWyrmModel): - """ an instance of a tag on a book by a user """ - - user = fields.ForeignKey( - "User", on_delete=models.PROTECT, activitypub_field="actor" - ) - book = fields.ForeignKey( - "Edition", on_delete=models.PROTECT, activitypub_field="object" - ) - tag = fields.ForeignKey("Tag", on_delete=models.PROTECT, activitypub_field="target") - - activity_serializer = activitypub.Add - object_field = "book" - collection_field = "tag" - - class Meta: - """ unqiueness constraint """ - - unique_together = ("user", "book", "tag") diff --git a/bookwyrm/tests/views/test_tag.py b/bookwyrm/tests/views/test_tag.py deleted file mode 100644 index 6ad6ab254..000000000 --- a/bookwyrm/tests/views/test_tag.py +++ /dev/null @@ -1,119 +0,0 @@ -""" test for app action functionality """ -from unittest.mock import patch -from django.contrib.auth.models import Group, Permission -from django.contrib.contenttypes.models import ContentType -from django.template.response import TemplateResponse -from django.test import TestCase -from django.test.client import RequestFactory - -from bookwyrm import models, views -from bookwyrm.activitypub import ActivitypubResponse - - -class TagViews(TestCase): - """ tag views""" - - def setUp(self): - """ we need basic test data and mocks """ - self.factory = RequestFactory() - self.local_user = models.User.objects.create_user( - "mouse@local.com", - "mouse@mouse.com", - "mouseword", - local=True, - localname="mouse", - remote_id="https://example.com/users/mouse", - ) - self.group = Group.objects.create(name="editor") - self.group.permissions.add( - Permission.objects.create( - name="edit_book", - codename="edit_book", - content_type=ContentType.objects.get_for_model(models.User), - ).id - ) - self.work = models.Work.objects.create(title="Test Work") - self.book = models.Edition.objects.create( - title="Example Edition", - remote_id="https://example.com/book/1", - parent_work=self.work, - ) - models.SiteSettings.objects.create() - - def test_tag_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = False - result = view(request, tag.identifier) - self.assertIsInstance(result, TemplateResponse) - result.render() - self.assertEqual(result.status_code, 200) - - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag_page_activitypub_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("", {"page": 1}) - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag(self): - """ add a tag to a book """ - view = views.AddTag.as_view() - request = self.factory.post( - "", - { - "name": "A Tag!?", - "book": self.book.id, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - tag = models.Tag.objects.get() - user_tag = models.UserTag.objects.get() - self.assertEqual(tag.name, "A Tag!?") - self.assertEqual(tag.identifier, "A+Tag%21%3F") - self.assertEqual(user_tag.user, self.local_user) - self.assertEqual(user_tag.book, self.book) - - def test_untag(self): - """ remove a tag from a book """ - view = views.RemoveTag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="A Tag!?") - models.UserTag.objects.create(user=self.local_user, book=self.book, tag=tag) - request = self.factory.post( - "", - { - "user": self.local_user.id, - "book": self.book.id, - "name": tag.name, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - self.assertTrue(models.Tag.objects.filter(name="A Tag!?").exists()) - self.assertFalse(models.UserTag.objects.exists()) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 463988065..0e48ef90c 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -245,11 +245,6 @@ urlpatterns = [ # author re_path(r"^author/(?P\d+)(.json)?/?$", views.Author.as_view()), re_path(r"^author/(?P\d+)/edit/?$", views.EditAuthor.as_view()), - # tags - re_path(r"^tag/(?P.+)\.json/?$", views.Tag.as_view()), - re_path(r"^tag/(?P.+)/?$", views.Tag.as_view()), - re_path(r"^tag/?$", views.AddTag.as_view()), - re_path(r"^untag/?$", views.RemoveTag.as_view()), # reading progress re_path(r"^edit-readthrough/?$", views.edit_readthrough, name="edit-readthrough"), re_path(r"^delete-readthrough/?$", views.delete_readthrough), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index d053e971b..d73a79ed0 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -32,7 +32,6 @@ from .shelf import create_shelf, delete_shelf from .shelf import shelve, unshelve from .site import Site from .status import CreateStatus, DeleteStatus, DeleteAndRedraft -from .tag import Tag, AddTag, RemoveTag from .updates import get_notification_count, get_unread_status_count from .user import User, EditUser, Followers, Following from .user_admin import UserAdmin diff --git a/bookwyrm/views/tag.py b/bookwyrm/views/tag.py deleted file mode 100644 index a6bdf05a2..000000000 --- a/bookwyrm/views/tag.py +++ /dev/null @@ -1,73 +0,0 @@ -""" tagging views""" -from django.contrib.auth.decorators import login_required -from django.shortcuts import get_object_or_404, redirect -from django.template.response import TemplateResponse -from django.utils.decorators import method_decorator -from django.views import View - -from bookwyrm import models -from bookwyrm.activitypub import ActivitypubResponse -from .helpers import is_api_request - - -# pylint: disable= no-self-use -class Tag(View): - """ tag page """ - - def get(self, request, tag_id): - """ see books related to a tag """ - tag_obj = get_object_or_404(models.Tag, identifier=tag_id) - - if is_api_request(request): - return ActivitypubResponse(tag_obj.to_activity(**request.GET)) - - books = models.Edition.objects.filter( - usertag__tag__identifier=tag_id - ).distinct() - data = { - "books": books, - "tag": tag_obj, - } - return TemplateResponse(request, "tag.html", data) - - -@method_decorator(login_required, name="dispatch") -class AddTag(View): - """ add a tag to a book """ - - def post(self, request): - """ tag a book """ - # I'm not using a form here because sometimes "name" is sent as a hidden - # field which doesn't validate - name = request.POST.get("name") - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - tag_obj, _ = models.Tag.objects.get_or_create( - name=name, - ) - models.UserTag.objects.get_or_create( - user=request.user, - book=book, - tag=tag_obj, - ) - - return redirect("/book/%s" % book_id) - - -@method_decorator(login_required, name="dispatch") -class RemoveTag(View): - """ remove a user's tag from a book """ - - def post(self, request): - """ untag a book """ - name = request.POST.get("name") - tag_obj = get_object_or_404(models.Tag, name=name) - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - - user_tag = get_object_or_404( - models.UserTag, tag=tag_obj, book=book, user=request.user - ) - user_tag.delete() - - return redirect("/book/%s" % book_id) From f6824268edac8a7bb86ca5c81afe9f284c40e67b Mon Sep 17 00:00:00 2001 From: Pablo Barton Date: Thu, 8 Apr 2021 12:05:21 -0400 Subject: [PATCH 002/109] 584 sorting of lists --- bookwyrm/forms.py | 19 +- .../0067_denullify_list_item_order.py | 30 + .../0068_ordering_for_list_items.py | 23 + bookwyrm/models/list.py | 8 +- bookwyrm/templates/lists/list.html | 35 +- .../snippets/booklist-pagination.html | 58 + bookwyrm/tests/models/test_list.py | 7 +- bookwyrm/tests/views/inbox/test_inbox_add.py | 1 + .../tests/views/inbox/test_inbox_remove.py | 1 + bookwyrm/tests/views/test_list.py | 158 +- bookwyrm/urls.py | 5 + bookwyrm/views/list.py | 156 +- locale/es/LC_MESSAGES/django.mo | Bin 26233 -> 26563 bytes locale/es/LC_MESSAGES/django.po | 1840 ++++++++++++++--- 14 files changed, 2048 insertions(+), 293 deletions(-) create mode 100644 bookwyrm/migrations/0067_denullify_list_item_order.py create mode 100644 bookwyrm/migrations/0068_ordering_for_list_items.py create mode 100644 bookwyrm/templates/snippets/booklist-pagination.html diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 7c41323c0..80b283109 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -3,7 +3,7 @@ import datetime from collections import defaultdict from django import forms -from django.forms import ModelForm, PasswordInput, widgets +from django.forms import ModelForm, PasswordInput, widgets, ChoiceField from django.forms.widgets import Textarea from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -287,3 +287,20 @@ class ServerForm(CustomForm): class Meta: model = models.FederatedServer exclude = ["remote_id"] + + +class SortListForm(forms.Form): + sort_by = ChoiceField( + choices=( + ("order", _("List Order")), + ("title", _("Book Title")), + ("rating", _("Rating")), + ), + label=_("Sort By"), + ) + direction = ChoiceField( + choices=( + ("ascending", _("Ascending")), + ("descending", _("Descending")), + ), + ) diff --git a/bookwyrm/migrations/0067_denullify_list_item_order.py b/bookwyrm/migrations/0067_denullify_list_item_order.py new file mode 100644 index 000000000..51e28371b --- /dev/null +++ b/bookwyrm/migrations/0067_denullify_list_item_order.py @@ -0,0 +1,30 @@ +from django.db import migrations + + +def forwards_func(apps, schema_editor): + # Set all values for ListItem.order + BookList = apps.get_model("bookwyrm", "List") + db_alias = schema_editor.connection.alias + for book_list in BookList.objects.using(db_alias).all(): + for i, item in enumerate(book_list.listitem_set.order_by("id"), 1): + item.order = i + item.save() + + +def reverse_func(apps, schema_editor): + # null all values for ListItem.order + BookList = apps.get_model("bookwyrm", "List") + db_alias = schema_editor.connection.alias + for book_list in BookList.objects.using(db_alias).all(): + for item in book_list.listitem_set.order_by("id"): + item.order = None + item.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0066_user_deactivation_reason"), + ] + + operations = [migrations.RunPython(forwards_func, reverse_func)] diff --git a/bookwyrm/migrations/0068_ordering_for_list_items.py b/bookwyrm/migrations/0068_ordering_for_list_items.py new file mode 100644 index 000000000..fa64f13c0 --- /dev/null +++ b/bookwyrm/migrations/0068_ordering_for_list_items.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.6 on 2021-04-08 16:15 + +import bookwyrm.models.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0067_denullify_list_item_order"), + ] + + operations = [ + migrations.AlterField( + model_name="listitem", + name="order", + field=bookwyrm.models.fields.IntegerField(), + ), + migrations.AlterUniqueTogether( + name="listitem", + unique_together={("order", "book_list"), ("book", "book_list")}, + ), + ] diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index 4d6b53cde..7e6de1069 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -67,7 +67,7 @@ class ListItem(CollectionItemMixin, BookWyrmModel): ) notes = fields.TextField(blank=True, null=True) approved = models.BooleanField(default=True) - order = fields.IntegerField(blank=True, null=True) + order = fields.IntegerField() endorsement = models.ManyToManyField("User", related_name="endorsers") activity_serializer = activitypub.ListItem @@ -93,7 +93,7 @@ class ListItem(CollectionItemMixin, BookWyrmModel): ) class Meta: - """ an opinionated constraint! you can't put a book on a list twice """ - - unique_together = ("book", "book_list") + # A book may only be placed into a list once, and each order in the list may be used only + # once + unique_together = (("book", "book_list"), ("order", "book_list")) ordering = ("-created_date",) diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index ace8aa634..3d3380977 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -13,10 +13,11 @@
- {% if not items.exists %} + {% include "snippets/booklist-pagination.html" with page=items %} + {% if not items.object_list.exists %}

{% trans "This list is currently empty" %}

{% else %} -
    +
      {% for item in items %}
    1. @@ -40,6 +41,16 @@ +
      +
@@ -49,8 +60,24 @@ {% endif %} - {% if request.user.is_authenticated and not list.curation == 'closed' or request.user == list.user %}
+

{% trans "Sort List" %}

+
+ +
+ {{ sort_form.sort_by }} +
+ +
+ {{ sort_form.direction }} +
+
+ +
+
+ {% if request.user.is_authenticated and not list.curation == 'closed' or request.user == list.user %}

{% if list.curation == 'open' or request.user == list.user %}{% trans "Add Books" %}{% else %}{% trans "Suggest Books" %}{% endif %}

@@ -93,7 +120,7 @@
{% endif %} {% endfor %} -
{% endif %} + {% endblock %} diff --git a/bookwyrm/templates/snippets/booklist-pagination.html b/bookwyrm/templates/snippets/booklist-pagination.html new file mode 100644 index 000000000..69fae52e8 --- /dev/null +++ b/bookwyrm/templates/snippets/booklist-pagination.html @@ -0,0 +1,58 @@ +{% load i18n %} +{% if page.has_other_pages %} + +{% endif %} diff --git a/bookwyrm/tests/models/test_list.py b/bookwyrm/tests/models/test_list.py index d99e54656..4e3460a91 100644 --- a/bookwyrm/tests/models/test_list.py +++ b/bookwyrm/tests/models/test_list.py @@ -51,6 +51,7 @@ class List(TestCase): book_list=book_list, book=self.book, user=self.local_user, + order=1, ) self.assertTrue(item.approved) @@ -65,7 +66,11 @@ class List(TestCase): ) item = models.ListItem.objects.create( - book_list=book_list, book=self.book, user=self.local_user, approved=False + book_list=book_list, + book=self.book, + user=self.local_user, + approved=False, + order=1, ) self.assertFalse(item.approved) diff --git a/bookwyrm/tests/views/inbox/test_inbox_add.py b/bookwyrm/tests/views/inbox/test_inbox_add.py index b2b653381..a5c629a8d 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_add.py +++ b/bookwyrm/tests/views/inbox/test_inbox_add.py @@ -94,6 +94,7 @@ class InboxAdd(TestCase): "type": "ListItem", "book": self.book.remote_id, "id": "https://bookwyrm.social/listbook/6189", + "order": 1, }, "target": "https://bookwyrm.social/user/mouse/list/to-read", "@context": "https://www.w3.org/ns/activitystreams", diff --git a/bookwyrm/tests/views/inbox/test_inbox_remove.py b/bookwyrm/tests/views/inbox/test_inbox_remove.py index a17154d11..8ac8740ad 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_remove.py +++ b/bookwyrm/tests/views/inbox/test_inbox_remove.py @@ -80,6 +80,7 @@ class InboxRemove(TestCase): user=self.local_user, book=self.book, book_list=booklist, + order=1, ) self.assertEqual(booklist.books.count(), 1) diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py index d669307cc..0b4339fc4 100644 --- a/bookwyrm/tests/views/test_list.py +++ b/bookwyrm/tests/views/test_list.py @@ -39,6 +39,18 @@ class ListViews(TestCase): remote_id="https://example.com/book/1", parent_work=work, ) + work_two = models.Work.objects.create(title="Labori") + self.book_two = models.Edition.objects.create( + title="Example Edition 2", + remote_id="https://example.com/book/2", + parent_work=work_two, + ) + work_three = models.Work.objects.create(title="Trabajar") + self.book_three = models.Edition.objects.create( + title="Example Edition 3", + remote_id="https://example.com/book/3", + parent_work=work_three, + ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user @@ -194,6 +206,7 @@ class ListViews(TestCase): user=self.local_user, book=self.book, approved=False, + order=1, ) request = self.factory.post( @@ -228,6 +241,7 @@ class ListViews(TestCase): user=self.local_user, book=self.book, approved=False, + order=1, ) request = self.factory.post( @@ -268,6 +282,145 @@ class ListViews(TestCase): self.assertEqual(item.user, self.local_user) self.assertTrue(item.approved) + def test_add_two_books(self): + """ + Putting two books on the list. The first should have an order value of + 1 and the second should have an order value of 2. + """ + request_one = self.factory.post( + "", + { + "book": self.book.id, + "list": self.list.id, + }, + ) + request_one.user = self.local_user + + request_two = self.factory.post( + "", + { + "book": self.book_two.id, + "list": self.list.id, + }, + ) + request_two.user = self.local_user + views.list.add_book(request_one) + views.list.add_book(request_two) + + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[1].book, self.book_two) + self.assertEqual(items[0].order, 1) + self.assertEqual(items[1].order, 2) + + def test_add_three_books_and_remove_second(self): + """ + Put three books on a list and then remove the one in the middle. The + ordering of the list should adjust to not have a gap. + """ + request_one = self.factory.post( + "", + { + "book": self.book.id, + "list": self.list.id, + }, + ) + request_one.user = self.local_user + + request_two = self.factory.post( + "", + { + "book": self.book_two.id, + "list": self.list.id, + }, + ) + request_two.user = self.local_user + + request_three = self.factory.post( + "", + { + "book": self.book_three.id, + "list": self.list.id, + }, + ) + request_three.user = self.local_user + + views.list.add_book(request_one) + views.list.add_book(request_two) + views.list.add_book(request_three) + + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[1].book, self.book_two) + self.assertEqual(items[2].book, self.book_three) + self.assertEqual(items[0].order, 1) + self.assertEqual(items[1].order, 2) + self.assertEqual(items[2].order, 3) + + remove_request = self.factory.post("", {"item": items[1].id}) + remove_request.user = self.local_user + views.list.remove_book(remove_request, self.list.id) + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[1].book, self.book_three) + self.assertEqual(items[0].order, 1) + self.assertEqual(items[1].order, 2) + + def test_add_three_books_and_move_last_to_first(self): + """ + Put three books on the list and move the last book to the first + position. + """ + request_one = self.factory.post( + "", + { + "book": self.book.id, + "list": self.list.id, + }, + ) + request_one.user = self.local_user + + request_two = self.factory.post( + "", + { + "book": self.book_two.id, + "list": self.list.id, + }, + ) + request_two.user = self.local_user + + request_three = self.factory.post( + "", + { + "book": self.book_three.id, + "list": self.list.id, + }, + ) + request_three.user = self.local_user + + views.list.add_book(request_one) + views.list.add_book(request_two) + views.list.add_book(request_three) + + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[1].book, self.book_two) + self.assertEqual(items[2].book, self.book_three) + self.assertEqual(items[0].order, 1) + self.assertEqual(items[1].order, 2) + self.assertEqual(items[2].order, 3) + + set_position_request = self.factory.post("", {"position": 1}) + set_position_request.user = self.local_user + views.list.set_book_position(set_position_request, items[2].id) + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book_three) + self.assertEqual(items[1].book, self.book) + self.assertEqual(items[2].book, self.book_two) + self.assertEqual(items[0].order, 1) + self.assertEqual(items[1].order, 2) + self.assertEqual(items[2].order, 3) + def test_add_book_outsider(self): """ put a book on a list """ self.list.curation = "open" @@ -358,6 +511,7 @@ class ListViews(TestCase): book_list=self.list, user=self.local_user, book=self.book, + order=1, ) self.assertTrue(self.list.listitem_set.exists()) @@ -377,9 +531,7 @@ class ListViews(TestCase): """ take an item off a list """ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): item = models.ListItem.objects.create( - book_list=self.list, - user=self.local_user, - book=self.book, + book_list=self.list, user=self.local_user, book=self.book, order=1 ) self.assertTrue(self.list.listitem_set.exists()) request = self.factory.post( diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index cf3f877b9..9e280f3e2 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -184,6 +184,11 @@ urlpatterns = [ views.list.remove_book, name="list-remove-book", ), + re_path( + r"^list-item/(?P\d+)/set-position$", + views.list.set_book_position, + name="list-set-book-position", + ), re_path( r"^list/(?P\d+)/curate/?$", views.Curate.as_view(), name="list-curate" ), diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 27e36dc5f..c7311bf12 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -1,8 +1,9 @@ """ book list views""" from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator -from django.db import IntegrityError -from django.db.models import Count, Q +from django.db import IntegrityError, transaction +from django.db.models import Avg, Count, Q, Max +from django.db.models.functions import Coalesce from django.http import HttpResponseNotFound, HttpResponseBadRequest from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse @@ -16,6 +17,7 @@ from bookwyrm.connectors import connector_manager from .helpers import is_api_request, privacy_filter from .helpers import get_user_from_username + # pylint: disable=no-self-use class Lists(View): """ book list page """ @@ -35,7 +37,6 @@ class Lists(View): .filter(item_count__gt=0) .order_by("-updated_date") .distinct() - .all() ) lists = privacy_filter( @@ -100,6 +101,43 @@ class List(View): query = request.GET.get("q") suggestions = None + + # sort_by shall be "order" unless a valid alternative is given + sort_by = request.GET.get("sort_by", "order") + if sort_by not in ("order", "title", "rating"): + sort_by = "order" + + # direction shall be "ascending" unless a valid alternative is given + direction = request.GET.get("direction", "ascending") + if direction not in ("ascending", "descending"): + direction = "ascending" + + page = request.GET.get("page", 1) + + if sort_by == "order": + directional_sort_by = "order" + if direction == "descending": + directional_sort_by = "-" + directional_sort_by + items = book_list.listitem_set.filter(approved=True).order_by( + directional_sort_by + ) + elif sort_by == "title": + directional_sort_by = "book__title" + if direction == "descending": + directional_sort_by = "-" + directional_sort_by + items = book_list.listitem_set.filter(approved=True).order_by( + directional_sort_by + ) + elif sort_by == "rating": + directional_sort_by = "average_rating" + if direction == "descending": + directional_sort_by = "-" + directional_sort_by + items = book_list.listitem_set.annotate( + average_rating=Avg(Coalesce("book__review__rating", 0)) + ).order_by(directional_sort_by) + + paginated = Paginator(items, 25) + if query and request.user.is_authenticated: # search for books suggestions = connector_manager.local_search(query, raw=True) @@ -119,11 +157,14 @@ class List(View): data = { "list": book_list, - "items": book_list.listitem_set.filter(approved=True), + "items": paginated.get_page(page), "pending_count": book_list.listitem_set.filter(approved=False).count(), "suggested_books": suggestions, "list_form": forms.ListForm(instance=book_list), "query": query or "", + "sort_form": forms.SortListForm( + {"direction": direction, "sort_by": sort_by} + ), } return TemplateResponse(request, "lists/list.html", data) @@ -168,7 +209,9 @@ class Curate(View): suggestion.approved = True suggestion.save() else: + deleted_order = suggestion.order suggestion.delete(broadcast=False) + normalize_book_list_ordering(book_list.id, start=deleted_order) return redirect("list-curate", book_list.id) @@ -179,6 +222,8 @@ def add_book(request): if not book_list.visible_to_user(request.user): return HttpResponseNotFound() + order_max = book_list.listitem_set.aggregate(Max("order"))["order__max"] or 0 + book = get_object_or_404(models.Edition, id=request.POST.get("book")) # do you have permission to add to the list? try: @@ -188,6 +233,7 @@ def add_book(request): book=book, book_list=book_list, user=request.user, + order=order_max + 1, ) elif book_list.curation == "curated": # make a pending entry @@ -196,6 +242,7 @@ def add_book(request): book=book, book_list=book_list, user=request.user, + order=order_max + 1, ) else: # you can't add to this list, what were you THINKING @@ -209,12 +256,101 @@ def add_book(request): @require_POST def remove_book(request, list_id): - """ put a book on a list """ - book_list = get_object_or_404(models.List, id=list_id) - item = get_object_or_404(models.ListItem, id=request.POST.get("item")) + """ remove a book from a list """ + with transaction.atomic(): + book_list = get_object_or_404(models.List, id=list_id) + item = get_object_or_404(models.ListItem, id=request.POST.get("item")) - if not book_list.user == request.user and not item.user == request.user: - return HttpResponseNotFound() + if not book_list.user == request.user and not item.user == request.user: + return HttpResponseNotFound() - item.delete() + deleted_order = item.order + item.delete() + normalize_book_list_ordering(book_list.id, start=deleted_order) return redirect("list", list_id) + + +@require_POST +def set_book_position(request, list_item_id): + """ + Action for when the list user manually specifies a list position, takes special care with the unique ordering per list + """ + with transaction.atomic(): + list_item = get_object_or_404(models.ListItem, id=list_item_id) + try: + int_position = int(request.POST.get("position")) + except ValueError: + return HttpResponseBadRequest( + "bad value for position. should be an integer" + ) + + if int_position < 1: + return HttpResponseBadRequest("position cannot be less than 1") + + book_list = list_item.book_list + order_max = book_list.listitem_set.aggregate(Max("order"))["order__max"] + + if int_position > order_max: + int_position = order_max + + if request.user not in (book_list.user, list_item.user): + return HttpResponseNotFound() + + original_order = list_item.order + if original_order == int_position: + return + elif original_order > int_position: + list_item.order = -1 + list_item.save() + increment_order_in_reverse(book_list.id, int_position, original_order) + else: + list_item.order = -1 + list_item.save() + decrement_order(book_list.id, original_order, int_position) + + list_item.order = int_position + list_item.save() + + return redirect("list", book_list.id) + + +@transaction.atomic +def increment_order_in_reverse(book_list_id, start, end): + try: + book_list = models.List.objects.get(id=book_list_id) + except models.List.DoesNotExist: + return + items = book_list.listitem_set.filter(order__gte=start, order__lt=end).order_by( + "-order" + ) + for item in items: + item.order += 1 + item.save() + + +@transaction.atomic +def decrement_order(book_list_id, start, end): + try: + book_list = models.List.objects.get(id=book_list_id) + except models.List.DoesNotExist: + return + items = book_list.listitem_set.filter(order__gt=start, order__lte=end).order_by( + "order" + ) + for item in items: + item.order -= 1 + item.save() + + +@transaction.atomic +def normalize_book_list_ordering(book_list_id, start=0, add_offset=0): + try: + book_list = models.List.objects.get(id=book_list_id) + except models.List.DoesNotExist: + return + items = book_list.listitem_set.filter(order__gt=start).order_by("order") + for i, item in enumerate(items, start): + effective_order = i + add_offset + if item.order != effective_order: + item.order = effective_order + item.save() diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index ea8eac7ee0281b38a66473d3814a646fc9fda0e3..d42d8394517c6921e9ae059a8a9affcf6fac1a68 100644 GIT binary patch delta 8531 zcmYk>3w+PjAII^tja|%U#@vSe*lh01=9=5w<}$aL$t4;amKnCWhF^+GlFLwX3x6q1 z(o*tADz}7^L^mNx6ovjSQUBNb`#qKO=(FcJ=X<{A_C4S4=KsHa*yqDfe7vW_ODr{{ zSw6;8#hB8@1o;|MzmjT=>EkgbAN%4Q+=rpqqlPhcaS%q}9E`*j*cjizGI$Xy;w`L( zVKt3O!-g1ZjMqFtMi(|A|CxjQpsl%#>Nq6Yn93N9iP#3!VIIcdGuQ;T;5a;IP32-P z;!mu8e!q)gCCZl%ZDC*gsLCyRwYT%$c?#jbZ z^&Zp!4N%t;?DbZt{=1_lIM_Nu`>z4UP{Ds@20yftji`=xpgP)vn(+bDN=~2#Jd3*j zimlg)RDEgGK$TI~YoP8+K=soO)o;(b?0X6Mwy$CB&JFpE);W1SE zZ!i{rLY;xIdd9Rs4{8DfQS}+9fhX9q7lSD;P$r1X3hM^z7SsUmq6XY=%g0b1p0@Q@ zunOhdsDaDZch62w)C7iDGp#xHdI1J<-TMR?P2gG7RxLxFiC55rn^A}HDC&l9QP1)M z>h-*d+RBgy?!?NY`inu`*U*;R*m5%JzI0@QUXw#c9TcDjcog*(%(nF}pmtylhTtYt z$Ju{8A&7^3&TCYfL=8l!fgHEN4{p*}oAQ5{dQ z^|MebScDi)f`>tCQA!Oy66H&FfhHgXL|=l!oqMmNTzCejhLqTZ;Lr(q}# zL#-$mwL=BA{4{C@pF<6})Yh*;^|#)Zx1bLDHq;IrLa$EsNirJXy49BtxK>=&S_O4u zH0s6{*3PI2rJ`2&AZp?xQ41P_dYxyW`d^6EaSifx%2*c^Zd1S{(N6GKnQAp zidYtFp|-j?s$CCMN2#a@46tURc4z`>0#Bk=ya3DKYOIB?qbB^h^&2l4-EbZ?;4i3& z{Dm4YD8cO@47Cyus(mbKB8^b(5^ebb)Wq7O7Shv}2csr5+LkAy4!3tU88uvu>Zk~H z=!#JT?nd3X*LoavsLr9?h9;;ETiJ3a)WlOz&v-Cuf@4tq%|i{e++JUc+Oe&uakgU+XhrR8!=9)P1|f&UWMV8%vDeq2Iw(T5dkZy@-Pi|@;!uog<^JU~6ZL4e zqIUQgs{N0x*ne%!O)4}{hX;(|KaOaui#+`A5btLxY!aK-;Hvw(kEo_atp);mos&ymwqkI?HbH_H00B%dtA;ACa{g|BlW?y`~eHN>mI$501xlT!hu|BGyKKj%*Az z!kUp^G22o1UBy}$(wR2{6EF`)VGe$Ua7}!I&_btc6Kp_F}^7x(-e21I=GIp zcn_WTyPNw=6Hu>f7t|MSDC%&HLpI5*Lrv%c>d;<6otfJhh5np$U5`agxFI@!|2HM0 z8MeYe?2URG9z?A?2es9Cs1D}gLM+5^jOpQSb#qktAyhx(QTz6XbStU34CiC{)T!+zP!vDARKjiBT*g2qpo*A52j)?=3{Mq9yNhI7=nkf27ZN_ z;9ca~WJ38!sQ<2BGU~W5>QD^FP@ImM*gPzaYfv2*+46SO0Q)c$kK6J&)T8><)(7!1 ziKJW!HE<&8?a4(w0`DR++QQ}N41{`yMW`9RXX_85IzEAVG*?g^-9jxOvX5I|A2so2 zsQ0})>X~Pw4)1u>BYqmo==Xmi8FjcGtKw$Vj1QqEaKU=jdJDBvK7HL4M4~1hjT*Qy zhG8evTht%5!0D*|9=FbO>UsW4Y{iS#^~lUj5$f>mL}!b!3gvUC3EV>uR!nsl&;m7Z z2h{a`*0HF={S<0pD^dMy$I^QLkCV~N&!7gnfqGy4`nfkoqpr6=O)Leqr9-eRjzDeo zL|eZEHQ)-=%HKfU_cp5k{kD7py{h|brMsWx z^4NfKOVlruQK*48pcYhY%O9X7@F{A?PN5Fpci0RsrL+HPP-B2=9n||8kD75m)Qm@> z4%v9rmd`*}+>!k*|XQ2#g0p2K^X^a)ANJ8B( z5OoMgp|ZL=P+*MC4Qm_{b)NqLGJ3Wr zFc#0DKD9wZ+yNp`E3A!r6z#DpcEgr964m}CbiNy?b~{lM+=u#7od0d~cmSPe@Ka|e#b%9LB7CX|MnXeMgl9Ml$1L`~d_n(#c-ed|#7 z?X=eq599f(gHu#!2hN~oc-=NM54$&nVR`C3s1-FuwNJJV!djHaq6RLsu0iLJqVC^@ zd`iqAoQR$buk)`evy2l|mx`mP0d8YC3?AHQ8!*h-Pb(J9pDkv zL<(>KdNCDGqE=jYr2FrK$50=vcTtbb`w1BhbPCnMc`S)nQ8WJ?b(sD_-4Hg)U0G#R zy$2^@JnH%@s2$vjK6r&tT0<-&b`p(rft2FI^B-;tIaFxNm3|`*5UYt!TyKL)9}(Ax z_QXEoJ>u`wk<1IWpdC|MObp=uX~gSJ&A&g=sO!x5PGXmw)Q!r|$<;#^?5t!1>R&oK z!KVnNVU(lXtn;%w<#=+wwyrbf*KB?U`F=zV$}@?jL=(y{VVswYQb}upTQrp^k0Z}- z;(yX*n|lfy+V-ldV(Y6>H|4(i>b5=`!>R9MuZ^diOk`2^>d?gy4eq;!v`B()Xvh|7h33W$_UgY0KKYOhy4k7AM7hvnYBmWKIq0Gn5Ndf%yrQDwQMbAH< zimpU!ds8;{C;mfS4V*=cA|9aJ5tRb*Gknr1v0Jvjr!8k#qo|)?ul1%bnfy(At&Hkx z5GRQw3O$Hjp2nHD5&ILfi95va#4$Z3eYE=0K)Fyr+lxo|y zXUL}!e-cWOF3uJUojiD^#G{ZZhyIBN*^VM8485<@O!Cu-6V&Ho7h*E;BjrBCw?r$-KKe=z zrZ9&1FHwP*O5C5yP^eG5NtETLTK8WhuixrQ<=}VWCxgK>+&f3+x(+gmGblWjIHa1&4@xGhHERZ0kMcEBIXba2&Gt}6m2RIO6v&^ z@d#0#@J92a5ux-hkwC+zu?NwC7)vNkCyo#kxn2=t@l$Lz3okHlKo5iE*^Mge{3+w^JVY=BU{L zf%zk{ax=4YM-?`T8|Cjw%Pz>tDqa+~z}MfcE{?1_vqZ_>d6`*x#f1$olnnLcWak%n z#*fR-F3292TR1WCY}mNG0#Apjrk_mVYH?cAqH;k_$62`rS%rUgE%Z?+T*af@Kn7Pb0Y%}+4=58)?H)0!doi-FR_d9=*RPHT`G@(@P43XO@ zCdwg~P?TGesdSQqRL<-D|9w3k&Uu{gqtBk-+wXh(T{ay&;ql;@hwHl#&n1R5*~6HM z_>-?Of05rCrdngRR5oS|ZpGPHEz+0(T#xbiF_yvWSOFhmT?~sdCJ@`BhU$fta3rST z0*o=nWv$}zs zwtYL6p#30f0mo1$coy}nxPBxPN#bj+<1#UoHza6!pJ;=lEGKXx#dDKoXp^mT!HSm4p6*oS$oE68T2B>3ghFAGx&=*IdPGBkq>iu6pMjx1b)WEyk4LlR59h^jeyn$NKUDN=cwVn2| zs2$cs^-DmVP%CS944^y+b=@e`LS~_--v5PU0`PUzPS&8l10UM*KGe<*q9*#>)}KNR zbl#S~M?Kv|sGUDTJ;Z)>obltVNvMssMVB&N$>_pfs0(wflTizrgWB1A)I;+YYA5fY zUf*pPfQ1-=XOKfOcWgO|UkG|ul2O-nL@lguUCv(@Otc-|Kuxp?wUEuI9q+a6hfoVX zj%?1HLoLv|p0hAN)ax6JK^TuZxhALuv_g&F8H4eedYr$GdN>v8I0LoAIj9B9vo1rO z&|1_2_Mmor2m|pnR>Nzk1()P|ErU`0!!a16Q42{x&DY#TMgydvc9M>|pbu&xS*VWB z+44x#!p5O?@`5cdLM`ZRTi$?rsCT3Kokopw1@)Hwh?>uJhm0+f2utHzsQ#N#C$b;4fy2nd>oTXwImPou10+yHlX^Qzz{r#+IbP`MDJrPdL$ZC1FNHt-v4wmT46ubtr(74 z$W+t-D^LTkv+dhZC-W(4;G?JoowDVNScdX-)O8P0;}mb;>^vBCT?G0wzlkNI1telw zY=e5Q`=B}w!CE*HJ7T`|CbprRkmUUGnuPijZZU@9Ce*Dsh`QIuQ42qVTG$12zyH_B zXy-qn7V;-*VqbpKXlJ45UNP$4#oBTLYM^GQiBeEI?S|^tA9ejOEREwZ24Au5TN-ly z8epI8ScqE43G9ZKus_yq-EK{#r`G1dv#mGTkfxijUO zIVac!)jtE%@L8A5?7|*Y_&0Zczh|PJ;^n9XZbaRJ0@OnHqVDA(+x~@ZKWY8OwqL_= z`W4|o^laf=pN$&Nl|!bX2k$M8p<;6~znQQ~OXpd5AN9KIME8+n1m*k4noU?MXQAm> zj`C29#F?0ZtFaP3z&H$R?fluEjL~}kv&rbfmoXMsArH1Win>sbcr}PXJ`tu3j>d^N z9B*MR_DXS1@CeSNT(K>`U@#x6;zQI)Mz(XFkr=lwV;Yn3p&=D@q#3BEwx6vZf_f`* zQLoi>)I*ntI@&d;57R#6RX4{`*L${ip7sEAzuu@@+6Ke0Ck8RU$t9zQYX-7uQ-D5r z5B0D-!pi8^!Ktr_T4(}#ViVNDlCcD)qh7cEs2z_+o$y3lgo{xNiRP7YRU?x~MiqTf z1B^foFafo*xu^+Opcb~qwy#G`d;m+~87zsHuq@t0y@sZf^Y?yJ)cAu@3(M`q{nsy# zaa8!?9MlIS4>j>BTffcL??)ZwG1LMtp!(fL-4fH;nIH)Du!f`B>!8|`F%r9B6&%%> z^N%C5gbGc(AEWRXYGJ=1-xl{rKr3&|$3O$NM&0`~)PhE!7Bmh0a54H~zAdjqf65=B z`WM>r85bGdo2$0rAy%MVD%F`d26;`)K-AICLLJ>)bWeo3b@`|TZngCvqsILVbxSUz z#wkK=z`v_g?}{L!mB*pp>!zrC-3RrQ4np1A$ry;UQ3Ec)intQB;Jv5?oVQ-F7NJh+ z4r&Ab-JFG&LFRRtXfj$+1B}6Ts2z?#4LH_1&DOtU%k!*DFpz%vsE2M724EqU$1|t} z+{Q>O`Lwfvcno5GlR!otQmg||PxU0!&K95sT8BFFLezh-*fx~@!jr#&9E zu;!=}O+}q>x-E~zQ06yN$Y{rlP!}vk4ZPNtci3_vs^1yZ(SL)Q@E&S`em$I97K_?Y z3tR4ux@DtKZ^ab!$HnMUW+fTjn~fNPJ5U!KK|MsLP)B{byT}h58VOO?}E>5yGMr8uO#X< z4Mr`vK5D^jQMafY24g?ef^xA8&Optx6xBaJgY(zXePBBr#IlsXMm>DLqTYfBsFMip z$u|JwQ3GY87Mz3bhZS{erlBTSZtLGgjk^)`$v$N3kGjaH<0;fhT(ljEP|w0`)D9k5 zgL*j&ibC~ognIbep-yZFYC)q>Col;${#*>hCDx6$-Bn0NJ2_{)gc{%m>VjV|7QK5r z6V^uUuqkR`y-_=R9yQ@i)b)9`yc~6lHeeHsM)jY9`Vua{D82t%$!LPpsE(IW z9dDv`@+azqiuZLU_C?*AFx1XtQSHr98)=IgFC8`BAk;|>L!Ho6)PfhFpWgqqWb|Ga zU@hE@t?&l6!}xyuZ&VzOdj0mGCjJ`3@mJJ>O7(XZQXVyNH0nfapiV3ibzMu;b-mD~ z3rE`yFQ9g^0CfUOQ9Jn%)o-WuFose-i`vmGRR6!MK?9sW*{Yx>?qE$vEhrOp{jdR? zKd-i#LB%*ci%HmdAiKsFQ4?&&()bB>#II00iR6jWNhP5Mo{V}6UbHSm9rbe5t=xv{ zw;Q|R!AzGkVCW#{@BIPz6b+lOI9@^B)9a|6{EknfdDi_$jp>f56!THn{fwF*GRs*= zJocoVh~05MYQvYYAvSPjJ71<;)IFPxnrH!PC(F?b-$M<&9`!KoK=nV2+Sv(Pe-_76 zzG2(@4|Yy)2zpTOMX+ag>P>|^f6Z33#{N`JvE}C0g&0eHRcuVek>8Jh5lVVU|0HG- zpA$-b>C>I4K%Tqm{?||wRS-3(PiGJ!k5BJ*cKnBMDiIFqH#3F+qPWt!-;Z~ z$KVB86f^0~&M>TN3*4jHRqp60>by znaoO^N*ro4|(0USBPe|V<`3@ zUZbu(QG&eQjvPX7!;>lE$pZPSw%po|r6SLqd5$P+>-5h)mmaE*iLZ%=L=Qr#F^zYf ztQk)}g?vA3g>gg~@=7;}cZs)%p9!TL+Nu#Joud2a5Xz$neP5I^$&c}1|G!aqj>40v z5oNtLO3#z$1Lscv;O8&IWg>>qyPZG`Bc3O25rM>U;{T-!R1RjmaN<|;i*){h6w-;u zsgO)fVh)jLE6-vD+vhy_R^+>2TigC4cDC)cZC!E7KDMqWuBHBa+xCI=E9U>NAI7bX5ly(t8v{kizPf#99>?I~s_cj(M z@`*!43qt9X13x+cQgkd!_9Ed+{6r{yMogkD2)`wE6SWAXR~<|*+B*=XD1S%<5TV3$ zBAEK2gi?UQa$p?#3mIYGqbX?vm%>j=QMAc89B6IVB{#DybH0}1)btvEmm+jev)TF yR-MaUc^Qe{7Nj&-S32*H4vP!&I@T**@MV`guYz$sN|q>?*C*7YU~gX^-~Rwz5oRv{ diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 64921d5e5..159e806ab 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-01 13:14-0700\n" +"POT-Creation-Date: 2021-04-11 01:59+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -49,6 +49,34 @@ msgstr "%(count)d usos" msgid "Unlimited" msgstr "Sin límite" +#: bookwyrm/forms.py:289 +msgid "List Order" +msgstr "Orden de la lista" + +#: bookwyrm/forms.py:290 +#| msgid "Title" +msgid "Book Title" +msgstr "Título" + +#: bookwyrm/forms.py:291 bookwyrm/templates/snippets/create_status_form.html:29 +#: bookwyrm/templates/user/shelf.html:81 +msgid "Rating" +msgstr "Calificación" + +#: bookwyrm/forms.py:293 bookwyrm/templates/lists/list.html:105 +msgid "Sort By" +msgstr "Ordenar por" + +#: bookwyrm/forms.py:297 +#| msgid "Started reading" +msgid "Ascending" +msgstr "Ascendente" + +#: bookwyrm/forms.py:298 +#| msgid "Started reading" +msgid "Descending" +msgstr "Descendente" + #: bookwyrm/models/fields.py:24 #, python-format msgid "%(value)s is not a valid remote_id" @@ -59,7 +87,7 @@ msgstr "%(value)s no es un remote_id válido" msgid "%(value)s is not a valid username" msgstr "%(value)s no es un usuario válido" -#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:157 +#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:152 msgid "username" msgstr "nombre de usuario" @@ -146,12 +174,12 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book.html:69 -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:223 msgid "OCLC Number:" msgstr "Número OCLC:" #: bookwyrm/templates/book/book.html:76 -#: bookwyrm/templates/book/edit_book.html:215 +#: bookwyrm/templates/book/edit_book.html:227 msgid "ASIN:" msgstr "ASIN:" @@ -171,17 +199,17 @@ msgid "Add Description" msgstr "Agregar descripción" #: bookwyrm/templates/book/book.html:107 -#: bookwyrm/templates/book/edit_book.html:101 +#: bookwyrm/templates/book/edit_book.html:107 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Descripción:" #: bookwyrm/templates/book/book.html:111 -#: bookwyrm/templates/book/edit_book.html:225 +#: bookwyrm/templates/book/edit_book.html:237 #: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:70 #: bookwyrm/templates/settings/site.html:93 -#: bookwyrm/templates/snippets/readthrough.html:65 +#: bookwyrm/templates/snippets/readthrough.html:75 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 @@ -190,12 +218,12 @@ msgstr "Guardar" #: bookwyrm/templates/book/book.html:112 bookwyrm/templates/book/book.html:161 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:226 +#: bookwyrm/templates/book/edit_book.html:238 #: bookwyrm/templates/edit_author.html:79 #: bookwyrm/templates/moderation/report_modal.html:32 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/readthrough.html:66 +#: bookwyrm/templates/snippets/readthrough.html:76 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:43 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:35 @@ -257,7 +285,7 @@ msgstr "Irse a lista" #: bookwyrm/templates/book/book.html:223 #: bookwyrm/templates/book/cover_modal.html:31 -#: bookwyrm/templates/lists/list.html:90 +#: bookwyrm/templates/lists/list.html:156 msgid "Add" msgstr "Agregar" @@ -266,14 +294,14 @@ msgid "rated it" msgstr "lo calificó con" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:163 +#: bookwyrm/templates/book/edit_book.html:175 #, fuzzy #| msgid "Add cover" msgid "Upload cover:" msgstr "Agregar portada" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:181 msgid "Load cover from url:" msgstr "" @@ -353,93 +381,93 @@ msgstr "Volver" msgid "Metadata" msgstr "Metadatos" -#: bookwyrm/templates/book/edit_book.html:91 +#: bookwyrm/templates/book/edit_book.html:92 msgid "Title:" msgstr "Título:" -#: bookwyrm/templates/book/edit_book.html:96 +#: bookwyrm/templates/book/edit_book.html:100 msgid "Subtitle:" msgstr "Subtítulo:" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:112 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:111 +#: bookwyrm/templates/book/edit_book.html:117 msgid "Series number:" msgstr "Número de serie:" -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:123 #, fuzzy #| msgid "Published" msgid "Publisher:" msgstr "Publicado" -#: bookwyrm/templates/book/edit_book.html:119 +#: bookwyrm/templates/book/edit_book.html:125 msgid "Separate multiple publishers with commas." msgstr "" -#: bookwyrm/templates/book/edit_book.html:125 +#: bookwyrm/templates/book/edit_book.html:132 msgid "First published date:" msgstr "Fecha de primera publicación:" -#: bookwyrm/templates/book/edit_book.html:130 +#: bookwyrm/templates/book/edit_book.html:140 msgid "Published date:" msgstr "Fecha de publicación:" -#: bookwyrm/templates/book/edit_book.html:137 +#: bookwyrm/templates/book/edit_book.html:149 #, fuzzy #| msgid "Author" msgid "Authors" msgstr "Autor/Autora" -#: bookwyrm/templates/book/edit_book.html:143 +#: bookwyrm/templates/book/edit_book.html:155 #, fuzzy, python-format #| msgid "Added by %(username)s" msgid "Remove %(name)s" msgstr "Agregado por %(username)s" -#: bookwyrm/templates/book/edit_book.html:148 +#: bookwyrm/templates/book/edit_book.html:160 #, fuzzy #| msgid "Edit Author" msgid "Add Authors:" msgstr "Editar Autor/Autora" -#: bookwyrm/templates/book/edit_book.html:149 +#: bookwyrm/templates/book/edit_book.html:161 msgid "John Doe, Jane Smith" msgstr "" -#: bookwyrm/templates/book/edit_book.html:155 +#: bookwyrm/templates/book/edit_book.html:167 #: bookwyrm/templates/user/shelf.html:75 msgid "Cover" msgstr "Portada:" -#: bookwyrm/templates/book/edit_book.html:182 +#: bookwyrm/templates/book/edit_book.html:194 msgid "Physical Properties" msgstr "Propiedades físicas:" -#: bookwyrm/templates/book/edit_book.html:183 +#: bookwyrm/templates/book/edit_book.html:195 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "Formato:" -#: bookwyrm/templates/book/edit_book.html:191 +#: bookwyrm/templates/book/edit_book.html:203 msgid "Pages:" msgstr "Páginas:" -#: bookwyrm/templates/book/edit_book.html:198 +#: bookwyrm/templates/book/edit_book.html:210 msgid "Book Identifiers" msgstr "Identificadores de libro" -#: bookwyrm/templates/book/edit_book.html:199 +#: bookwyrm/templates/book/edit_book.html:211 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:203 +#: bookwyrm/templates/book/edit_book.html:215 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:207 +#: bookwyrm/templates/book/edit_book.html:219 #: bookwyrm/templates/edit_author.html:59 msgid "Openlibrary key:" msgstr "Clave OpenLibrary:" @@ -497,12 +525,18 @@ msgstr "" #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 -#: bookwyrm/templates/feed/feed_layout.html:57 +#: bookwyrm/templates/feed/feed_layout.html:70 #: bookwyrm/templates/get_started/layout.html:19 #: bookwyrm/templates/get_started/layout.html:52 msgid "Close" msgstr "Cerrar" +#: bookwyrm/templates/compose.html:5 bookwyrm/templates/compose.html:8 +#, fuzzy +#| msgid "Boost status" +msgid "Compose status" +msgstr "Status de respaldo" + #: bookwyrm/templates/directory/community_filter.html:5 #, fuzzy #| msgid "Comment" @@ -523,7 +557,7 @@ msgstr "Federalizado" #: bookwyrm/templates/directory/directory.html:6 #: bookwyrm/templates/directory/directory.html:11 -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:92 msgid "Directory" msgstr "" @@ -844,23 +878,23 @@ msgstr "Tus libros" msgid "There are no books here right now! Try searching for a book to get started" msgstr "¡No hay ningún libro aqui ahorita! Busca a un libro para empezar" -#: bookwyrm/templates/feed/feed_layout.html:23 +#: bookwyrm/templates/feed/feed_layout.html:24 #: bookwyrm/templates/user/shelf.html:28 msgid "To Read" msgstr "Para leer" -#: bookwyrm/templates/feed/feed_layout.html:24 +#: bookwyrm/templates/feed/feed_layout.html:25 #: bookwyrm/templates/user/shelf.html:28 msgid "Currently Reading" msgstr "Leyendo actualmente" -#: bookwyrm/templates/feed/feed_layout.html:25 +#: bookwyrm/templates/feed/feed_layout.html:26 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:11 #: bookwyrm/templates/user/shelf.html:28 msgid "Read" msgstr "Leer" -#: bookwyrm/templates/feed/feed_layout.html:74 bookwyrm/templates/goal.html:26 +#: bookwyrm/templates/feed/feed_layout.html:88 bookwyrm/templates/goal.html:26 #: bookwyrm/templates/snippets/goal_card.html:6 #, python-format msgid "%(year)s Reading Goal" @@ -893,7 +927,7 @@ msgid "What are you reading?" msgstr "Lectura se empezó" #: bookwyrm/templates/get_started/books.html:9 -#: bookwyrm/templates/lists/list.html:58 +#: bookwyrm/templates/lists/list.html:124 msgid "Search for a book" msgstr "Buscar libros" @@ -914,7 +948,7 @@ msgstr "" #: bookwyrm/templates/get_started/users.html:18 #: bookwyrm/templates/get_started/users.html:19 #: bookwyrm/templates/layout.html:37 bookwyrm/templates/layout.html:38 -#: bookwyrm/templates/lists/list.html:62 +#: bookwyrm/templates/lists/list.html:128 msgid "Search" msgstr "Buscar" @@ -931,7 +965,7 @@ msgid "Popular on %(site_name)s" msgstr "Sobre %(site_name)s" #: bookwyrm/templates/get_started/books.html:51 -#: bookwyrm/templates/lists/list.html:75 +#: bookwyrm/templates/lists/list.html:141 msgid "No books found" msgstr "No se encontró ningún libro" @@ -1055,7 +1089,7 @@ msgid "%(username)s's %(year)s Books" msgstr "Los libros de %(username)s para %(year)s" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/layout.html:102 +#: bookwyrm/templates/layout.html:97 msgid "Import Books" msgstr "Importar libros" @@ -1196,16 +1230,11 @@ msgstr "Menú de navigación central" msgid "Feed" msgstr "Actividad" -#: bookwyrm/templates/layout.html:92 -#: bookwyrm/templates/preferences/preferences_layout.html:14 -msgid "Profile" -msgstr "Perfil" - -#: bookwyrm/templates/layout.html:107 +#: bookwyrm/templates/layout.html:102 msgid "Settings" msgstr "Configuración" -#: bookwyrm/templates/layout.html:116 +#: bookwyrm/templates/layout.html:111 #: bookwyrm/templates/settings/admin_layout.html:24 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 @@ -1213,57 +1242,57 @@ msgstr "Configuración" msgid "Invites" msgstr "Invitaciones" -#: bookwyrm/templates/layout.html:123 +#: bookwyrm/templates/layout.html:118 msgid "Admin" msgstr "" -#: bookwyrm/templates/layout.html:130 +#: bookwyrm/templates/layout.html:125 msgid "Log out" msgstr "Cerrar sesión" -#: bookwyrm/templates/layout.html:138 bookwyrm/templates/layout.html:139 +#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:10 msgid "Notifications" msgstr "Notificaciones" -#: bookwyrm/templates/layout.html:156 bookwyrm/templates/layout.html:160 +#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nombre de usuario:" -#: bookwyrm/templates/layout.html:161 +#: bookwyrm/templates/layout.html:156 msgid "password" msgstr "contraseña" -#: bookwyrm/templates/layout.html:162 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" -#: bookwyrm/templates/layout.html:165 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "Iniciar sesión" -#: bookwyrm/templates/layout.html:173 +#: bookwyrm/templates/layout.html:168 msgid "Join" msgstr "" -#: bookwyrm/templates/layout.html:196 +#: bookwyrm/templates/layout.html:191 msgid "About this server" msgstr "Sobre este servidor" -#: bookwyrm/templates/layout.html:200 +#: bookwyrm/templates/layout.html:195 msgid "Contact site admin" msgstr "Contactarse con administradores del sitio" -#: bookwyrm/templates/layout.html:207 +#: bookwyrm/templates/layout.html:202 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "" -#: bookwyrm/templates/layout.html:211 +#: bookwyrm/templates/layout.html:206 msgid "BookWyrm is open source software. You can contribute or report issues on GitHub." msgstr "BookWyrm es software de código abierto. Puedes contribuir o reportar problemas en GitHub." @@ -1342,45 +1371,74 @@ msgstr "Abierto" msgid "Anyone can add books to this list" msgstr "Cualquer usuario puede agregar libros a esta lista" -#: bookwyrm/templates/lists/list.html:17 +#: bookwyrm/templates/lists/list.html:19 +#: bookwyrm/templates/snippets/pagination.html:12 +msgid "Previous" +msgstr "Anterior" + +#: bookwyrm/templates/lists/list.html:22 +#: bookwyrm/templates/snippets/pagination.html:23 +msgid "Next" +msgstr "Siguiente" + +#: bookwyrm/templates/lists/list.html:58 msgid "This list is currently empty" msgstr "Esta lista está vacia" -#: bookwyrm/templates/lists/list.html:35 +#: bookwyrm/templates/lists/list.html:76 #, python-format msgid "Added by %(username)s" msgstr "Agregado por %(username)s" -#: bookwyrm/templates/lists/list.html:41 -#: bookwyrm/templates/snippets/shelf_selector.html:28 +#: bookwyrm/templates/lists/list.html:82 +#: bookwyrm/templates/snippets/shelf_selector.html:26 msgid "Remove" msgstr "Quitar" -#: bookwyrm/templates/lists/list.html:54 +#: bookwyrm/templates/lists/list.html:90 +msgid "Set list position" +msgstr "Apunta indice" + +#: bookwyrm/templates/lists/list.html:103 +#: bookwyrm/templates/lists/list.html:115 +msgid "Sort List" +msgstr "Ordena la lista" + +#: bookwyrm/templates/lists/list.html:109 +#, fuzzy +#| msgid "List curation:" +msgid "Direction" +msgstr "Enumerar lista de comisariado:" + +#: bookwyrm/templates/lists/list.html:120 msgid "Add Books" msgstr "Agregar libros" -#: bookwyrm/templates/lists/list.html:54 +#: bookwyrm/templates/lists/list.html:120 msgid "Suggest Books" msgstr "Sugerir libros" -#: bookwyrm/templates/lists/list.html:63 +#: bookwyrm/templates/lists/list.html:129 msgid "search" msgstr "buscar" -#: bookwyrm/templates/lists/list.html:69 +#: bookwyrm/templates/lists/list.html:135 msgid "Clear search" msgstr "Borrar búsqueda" -#: bookwyrm/templates/lists/list.html:74 +#: bookwyrm/templates/lists/list.html:140 #, python-format msgid "No books found matching the query \"%(query)s\"" msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query)s\"" -#: bookwyrm/templates/lists/list.html:90 +#: bookwyrm/templates/lists/list.html:156 msgid "Suggest" msgstr "Sugerir" +#: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 +msgid "Your Lists" +msgstr "Tus listas" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "Iniciar sesión" @@ -1422,7 +1480,7 @@ msgid "View user profile" msgstr "Perfil de usuario" #: bookwyrm/templates/moderation/report.html:22 -#: bookwyrm/templates/snippets/status/status_options.html:25 +#: bookwyrm/templates/snippets/status/status_options.html:35 #: bookwyrm/templates/snippets/user_options.html:13 msgid "Send direct message" msgstr "Enviar mensaje directo" @@ -1440,8 +1498,8 @@ msgid "Moderator Comments" msgstr "" #: bookwyrm/templates/moderation/report.html:54 -#: bookwyrm/templates/snippets/create_status.html:12 -#: bookwyrm/templates/snippets/create_status_form.html:52 +#: bookwyrm/templates/snippets/create_status.html:28 +#: bookwyrm/templates/snippets/create_status_form.html:44 msgid "Comment" msgstr "Comentario" @@ -1698,6 +1756,10 @@ msgstr "Huso horario preferido" msgid "Account" msgstr "Cuenta" +#: bookwyrm/templates/preferences/preferences_layout.html:14 +msgid "Profile" +msgstr "Perfil" + #: bookwyrm/templates/preferences/preferences_layout.html:20 msgid "Relationships" msgstr "Relaciones" @@ -1854,7 +1916,8 @@ msgid "Software" msgstr "Software" #: bookwyrm/templates/settings/federation.html:24 -#: bookwyrm/templates/settings/manage_invite_requests.html:33 +#: bookwyrm/templates/settings/manage_invite_requests.html:44 +#: bookwyrm/templates/settings/status_filter.html:5 #: bookwyrm/templates/settings/user_admin.html:32 msgid "Status" msgstr "Status" @@ -1872,61 +1935,72 @@ msgstr "Invitaciones" msgid "Ignored Invite Requests" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:31 -msgid "Date" -msgstr "" +#: bookwyrm/templates/settings/manage_invite_requests.html:35 +#, fuzzy +#| msgid "Federated" +msgid "Date requested" +msgstr "Federalizado" -#: bookwyrm/templates/settings/manage_invite_requests.html:32 +#: bookwyrm/templates/settings/manage_invite_requests.html:39 +#, fuzzy +#| msgid "Accept" +msgid "Date accepted" +msgstr "Aceptar" + +#: bookwyrm/templates/settings/manage_invite_requests.html:42 msgid "Email" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:34 +#: bookwyrm/templates/settings/manage_invite_requests.html:47 #, fuzzy #| msgid "Notifications" msgid "Action" msgstr "Notificaciones" -#: bookwyrm/templates/settings/manage_invite_requests.html:37 +#: bookwyrm/templates/settings/manage_invite_requests.html:50 #, fuzzy #| msgid "Follow Requests" msgid "No requests" msgstr "Solicitudes de seguidor" -#: bookwyrm/templates/settings/manage_invite_requests.html:45 +#: bookwyrm/templates/settings/manage_invite_requests.html:59 +#: bookwyrm/templates/settings/status_filter.html:16 #, fuzzy #| msgid "Accept" msgid "Accepted" msgstr "Aceptar" -#: bookwyrm/templates/settings/manage_invite_requests.html:47 +#: bookwyrm/templates/settings/manage_invite_requests.html:61 +#: bookwyrm/templates/settings/status_filter.html:12 msgid "Sent" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:49 +#: bookwyrm/templates/settings/manage_invite_requests.html:63 +#: bookwyrm/templates/settings/status_filter.html:8 msgid "Requested" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:57 +#: bookwyrm/templates/settings/manage_invite_requests.html:73 msgid "Send invite" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:59 +#: bookwyrm/templates/settings/manage_invite_requests.html:75 msgid "Re-send invite" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:70 +#: bookwyrm/templates/settings/manage_invite_requests.html:95 msgid "Ignore" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:72 -msgid "Un-gnore" +#: bookwyrm/templates/settings/manage_invite_requests.html:97 +msgid "Un-ignore" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:83 +#: bookwyrm/templates/settings/manage_invite_requests.html:108 msgid "Back to pending requests" msgstr "" -#: bookwyrm/templates/settings/manage_invite_requests.html:85 +#: bookwyrm/templates/settings/manage_invite_requests.html:110 msgid "View ignored requests" msgstr "" @@ -2080,8 +2154,8 @@ msgstr "%(title)s por " #: bookwyrm/templates/snippets/boost_button.html:8 #: bookwyrm/templates/snippets/boost_button.html:9 -#: bookwyrm/templates/snippets/status/status_body.html:51 #: bookwyrm/templates/snippets/status/status_body.html:52 +#: bookwyrm/templates/snippets/status/status_body.html:53 msgid "Boost status" msgstr "Status de respaldo" @@ -2094,15 +2168,15 @@ msgstr "Status de des-respaldo" msgid "Spoiler alert:" msgstr "Alerta de spoiler:" -#: bookwyrm/templates/snippets/content_warning_field.html:4 +#: bookwyrm/templates/snippets/content_warning_field.html:10 msgid "Spoilers ahead!" msgstr "¡Advertencia, ya vienen spoilers!" -#: bookwyrm/templates/snippets/create_status.html:9 +#: bookwyrm/templates/snippets/create_status.html:17 msgid "Review" msgstr "Reseña" -#: bookwyrm/templates/snippets/create_status.html:15 +#: bookwyrm/templates/snippets/create_status.html:39 msgid "Quote" msgstr "Cita" @@ -2124,52 +2198,41 @@ msgstr "Cita" msgid "Review:" msgstr "Reseña" -#: bookwyrm/templates/snippets/create_status_form.html:29 -#: bookwyrm/templates/user/shelf.html:81 -msgid "Rating" -msgstr "Calificación" - -#: bookwyrm/templates/snippets/create_status_form.html:31 -#: bookwyrm/templates/snippets/rate_action.html:14 -#: bookwyrm/templates/snippets/stars.html:3 -msgid "No rating" -msgstr "No calificación" - -#: bookwyrm/templates/snippets/create_status_form.html:64 +#: bookwyrm/templates/snippets/create_status_form.html:56 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 msgid "Progress:" msgstr "Progreso:" -#: bookwyrm/templates/snippets/create_status_form.html:71 +#: bookwyrm/templates/snippets/create_status_form.html:63 #: bookwyrm/templates/snippets/readthrough_form.html:22 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "páginas" -#: bookwyrm/templates/snippets/create_status_form.html:72 +#: bookwyrm/templates/snippets/create_status_form.html:64 #: bookwyrm/templates/snippets/readthrough_form.html:23 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "por ciento" -#: bookwyrm/templates/snippets/create_status_form.html:77 +#: bookwyrm/templates/snippets/create_status_form.html:69 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "de %(pages)s páginas" -#: bookwyrm/templates/snippets/create_status_form.html:89 +#: bookwyrm/templates/snippets/create_status_form.html:81 msgid "Include spoiler alert" msgstr "Incluir alerta de spoiler" -#: bookwyrm/templates/snippets/create_status_form.html:95 +#: bookwyrm/templates/snippets/create_status_form.html:88 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 #: bookwyrm/templates/snippets/privacy_select.html:19 msgid "Private" msgstr "Privada" -#: bookwyrm/templates/snippets/create_status_form.html:102 +#: bookwyrm/templates/snippets/create_status_form.html:99 msgid "Post" msgstr "Compartir" @@ -2184,13 +2247,14 @@ msgstr "Estás eliminando esta lectura y sus %(count)s actualizaciones de progre #: bookwyrm/templates/snippets/delete_readthrough_modal.html:15 #: bookwyrm/templates/snippets/follow_request_buttons.html:13 +#: venv/lib/python3.8/site-packages/django/forms/formsets.py:391 msgid "Delete" msgstr "Eliminar" #: bookwyrm/templates/snippets/fav_button.html:7 #: bookwyrm/templates/snippets/fav_button.html:8 -#: bookwyrm/templates/snippets/status/status_body.html:55 #: bookwyrm/templates/snippets/status/status_body.html:56 +#: bookwyrm/templates/snippets/status/status_body.html:57 msgid "Like status" msgstr "Me gusta status" @@ -2209,11 +2273,11 @@ msgstr "Mostrar menos" msgid "Hide filters" msgstr "" -#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:19 +#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:22 msgid "Apply filters" msgstr "" -#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:23 +#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:26 #, fuzzy #| msgid "Clear search" msgid "Clear filters" @@ -2237,6 +2301,19 @@ msgstr "Dejar de seguir" msgid "Accept" msgstr "Aceptar" +#: bookwyrm/templates/snippets/form_rate_stars.html:20 +#: bookwyrm/templates/snippets/stars.html:13 +msgid "No rating" +msgstr "No calificación" + +#: bookwyrm/templates/snippets/form_rate_stars.html:45 +#: bookwyrm/templates/snippets/stars.html:7 +#, python-format +msgid "%(rating)s star" +msgid_plural "%(rating)s stars" +msgstr[0] "" +msgstr[1] "" + #: bookwyrm/templates/snippets/generated_status/goal.html:1 #, python-format msgid "set a goal to read %(counter)s book in %(year)s" @@ -2311,13 +2388,17 @@ msgstr "Has leído %(read_count)s de %(goal_count)s libros< msgid "%(username)s has read %(read_count)s of %(goal_count)s books." msgstr "%(username)s ha leído %(read_count)s de %(goal_count)s libros." -#: bookwyrm/templates/snippets/pagination.html:7 -msgid "Previous" -msgstr "Anterior" +#: bookwyrm/templates/snippets/page_text.html:4 +#, fuzzy, python-format +#| msgid "of %(pages)s pages" +msgid "page %(page)s of %(total_pages)s" +msgstr "de %(pages)s páginas" -#: bookwyrm/templates/snippets/pagination.html:15 -msgid "Next" -msgstr "Siguiente" +#: bookwyrm/templates/snippets/page_text.html:6 +#, fuzzy, python-format +#| msgid "%(pages)s pages" +msgid "page %(page)s" +msgstr "%(pages)s páginas" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 @@ -2348,7 +2429,7 @@ msgstr "Seguidores" msgid "Leave a rating" msgstr "Da una calificación" -#: bookwyrm/templates/snippets/rate_action.html:29 +#: bookwyrm/templates/snippets/rate_action.html:19 msgid "Rate" msgstr "Calificar" @@ -2356,28 +2437,28 @@ msgstr "Calificar" msgid "Progress Updates:" msgstr "Actualizaciones de progreso:" -#: bookwyrm/templates/snippets/readthrough.html:12 +#: bookwyrm/templates/snippets/readthrough.html:14 msgid "finished" msgstr "terminado" -#: bookwyrm/templates/snippets/readthrough.html:15 +#: bookwyrm/templates/snippets/readthrough.html:25 msgid "Show all updates" msgstr "Mostrar todas las actualizaciones" -#: bookwyrm/templates/snippets/readthrough.html:31 +#: bookwyrm/templates/snippets/readthrough.html:41 msgid "Delete this progress update" msgstr "Eliminar esta actualización de progreso" -#: bookwyrm/templates/snippets/readthrough.html:41 +#: bookwyrm/templates/snippets/readthrough.html:51 msgid "started" msgstr "empezado" -#: bookwyrm/templates/snippets/readthrough.html:47 -#: bookwyrm/templates/snippets/readthrough.html:61 +#: bookwyrm/templates/snippets/readthrough.html:57 +#: bookwyrm/templates/snippets/readthrough.html:71 msgid "Edit read dates" msgstr "Editar fechas de lectura" -#: bookwyrm/templates/snippets/readthrough.html:51 +#: bookwyrm/templates/snippets/readthrough.html:61 msgid "Delete these read dates" msgstr "Eliminar estas fechas de lectura" @@ -2501,9 +2582,9 @@ msgstr "respaldó" msgid "Delete status" msgstr "Eliminar status" -#: bookwyrm/templates/snippets/status/status_body.html:34 -#: bookwyrm/templates/snippets/status/status_body.html:47 +#: bookwyrm/templates/snippets/status/status_body.html:35 #: bookwyrm/templates/snippets/status/status_body.html:48 +#: bookwyrm/templates/snippets/status/status_body.html:49 msgid "Reply" msgstr "Respuesta" @@ -2550,6 +2631,12 @@ msgstr "respondió a tu tag or including the “Referrer-Policy: no-referrer” header, please remove them. The CSRF protection requires the “Referer” header to do strict referer checking. If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/csrf.py:132 +msgid "You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/csrf.py:137 +msgid "If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for “same-origin” requests." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/csrf.py:142 +msgid "More information is available with DEBUG=True." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:41 +msgid "No year specified" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:61 +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:111 +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:208 +msgid "Date out of range" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:90 +msgid "No month specified" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:142 +msgid "No day specified" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:188 +msgid "No week specified" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:338 +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:367 +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:589 +#, python-format +msgid "Future %(verbose_name_plural)s not available because %(class_name)s.allow_future is False." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:623 +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/detail.py:54 +#, fuzzy, python-format +#| msgid "No books found matching the query \"%(query)s\"" +msgid "No %(verbose_name)s found matching the query" +msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query)s\"" + +#: venv/lib/python3.8/site-packages/django/views/generic/list.py:67 +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/list.py:72 +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/generic/list.py:154 +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/static.py:40 +msgid "Directory indexes are not allowed here." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/static.py:42 +#, fuzzy, python-format +#| msgid "%(value)s is not a valid username" +msgid "“%(path)s” does not exist" +msgstr "%(value)s no es un usuario válido" + +#: venv/lib/python3.8/site-packages/django/views/static.py:80 +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:7 +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:346 +#, python-format +msgid "View release notes for Django %(version)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:368 +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:369 +#, python-format +msgid "You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs." +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:384 +msgid "Django Documentation" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:385 +msgid "Topics, references, & how-to’s" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:396 +msgid "Tutorial: A Polling App" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:397 +msgid "Get started with Django" +msgstr "" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:408 +#, fuzzy +#| msgid "Comment" +msgid "Django Community" +msgstr "Comentario" + +#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:409 +msgid "Connect, get help, or contribute" +msgstr "" + +#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1301 +#, python-format +msgid "Attempting to connect to qpid with SASL mechanism %s" +msgstr "" + +#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1306 +#, python-format +msgid "Connected to qpid with SASL mechanism %s" +msgstr "" + +#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1324 +#, python-format +msgid "Unable to connect to qpid with SASL mechanism %s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:371 +msgid "1 second ago" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:377 +msgid "1 minute ago" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:382 +msgid "1 hour ago" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:385 +#, python-format +msgid "%(time)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:387 +msgid "yesterday" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:387 +#, python-format +msgid "yesterday at %(time)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:389 +#, python-format +msgid "%(weekday)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:389 +#, python-format +msgid "%(weekday)s at %(time)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:392 +#: venv/lib/python3.8/site-packages/tornado/locale.py:445 +#, python-format +msgid "%(month_name)s %(day)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:394 +#, python-format +msgid "%(month_name)s %(day)s at %(time)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:399 +#, python-format +msgid "%(month_name)s %(day)s, %(year)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:401 +#, python-format +msgid "%(month_name)s %(day)s, %(year)s at %(time)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:439 +#, python-format +msgid "%(weekday)s, %(month_name)s %(day)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/locale.py:462 +#, python-format +msgid "%(commas)s and %(last)s" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:68 +msgctxt "law" +msgid "right" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:69 +msgctxt "good" +msgid "right" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:71 +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:74 +msgctxt "organization" +msgid "club" +msgstr "" + +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:76 +#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:77 +msgctxt "stick" +msgid "club" +msgstr "" + #, fuzzy #~| msgid "Started" #~ msgid "Getting Started" #~ msgstr "Empezado" -#, fuzzy, python-format +#, fuzzy #~| msgid "No users found for \"%(query)s\"" #~ msgid "No users were found for \"%(query)s\"" #~ msgstr "No se encontró ningún usuario correspondiente a \"%(query)s\"" @@ -2757,7 +4188,6 @@ msgstr "" #~ msgid "Your lists" #~ msgstr "Tus listas" -#, python-format #~ msgid "See all %(size)s lists" #~ msgstr "Ver las %(size)s listas" @@ -2782,148 +4212,18 @@ msgstr "" #~ msgid "Your Shelves" #~ msgstr "Tus estantes" -#, python-format #~ msgid "%(username)s: Shelves" #~ msgstr "%(username)s: Estantes" #~ msgid "Shelves" #~ msgstr "Estantes" -#, python-format #~ msgid "See all %(shelf_count)s shelves" #~ msgstr "Ver los %(shelf_count)s estantes" #~ msgid "Send follow request" #~ msgstr "Envia solicitud de seguidor" -#, fuzzy -#~| msgid "All messages" -#~ msgid "Messages" -#~ msgstr "Todos los mensajes" - -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Enter a valid email address." -#~ msgstr "Dirección de correo electrónico:" - -#, fuzzy -#~| msgid "Series number:" -#~ msgid "Enter a number." -#~ msgstr "Número de serie:" - -#, fuzzy -#~| msgid "%(value)s is not a valid remote_id" -#~ msgid "Value %(value)r is not a valid choice." -#~ msgstr "%(value)s no es un remote_id válido" - -#, fuzzy -#~| msgid "Series number:" -#~ msgid "Decimal number" -#~ msgstr "Número de serie:" - -#, fuzzy -#~| msgid "List curation:" -#~ msgid "Duration" -#~ msgstr "Enumerar lista de comisariado:" - -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Email address" -#~ msgstr "Dirección de correo electrónico:" - -#, fuzzy -#~| msgid "Email address:" -#~ msgid "IPv4 address" -#~ msgstr "Dirección de correo electrónico:" - -#, fuzzy -#~| msgid "Email address:" -#~ msgid "IP address" -#~ msgstr "Dirección de correo electrónico:" - -#, fuzzy -#~| msgid "No active invites" -#~ msgid "Positive integer" -#~ msgstr "No invitaciónes activas" - -#, fuzzy -#~| msgid "%(value)s is not a valid username" -#~ msgid "“%(value)s” is not a valid UUID." -#~ msgstr "%(value)s no es un usuario válido" - -#, fuzzy -#~| msgid "Images" -#~ msgid "Image" -#~ msgstr "Imagenes" - -#, fuzzy -#~| msgid "Relationships" -#~ msgid "One-to-one relationship" -#~ msgstr "Relaciones" - -#, fuzzy -#~| msgid "This shelf is empty." -#~ msgid "This field is required." -#~ msgstr "Este estante está vacio." - -#, fuzzy -#~| msgid "This shelf is empty." -#~ msgid "The submitted file is empty." -#~ msgstr "Este estante está vacio." - -#, fuzzy -#~| msgid "%(value)s is not a valid username" -#~ msgid "“%(pk)s” is not a valid value." -#~ msgstr "%(value)s no es un usuario válido" - -#, fuzzy -#~| msgid "Currently Reading" -#~ msgid "Currently" -#~ msgstr "Leyendo actualmente" - -#, fuzzy -#~| msgid "Change shelf" -#~ msgid "Change" -#~ msgstr "Cambiar estante" - -#, fuzzy -#~| msgid "Status" -#~ msgid "Sat" -#~ msgstr "Status" - -#, fuzzy -#~| msgid "Search" -#~ msgid "March" -#~ msgstr "Buscar" - -#, fuzzy -#~| msgid "Series number:" -#~ msgid "September" -#~ msgstr "Número de serie:" - -#, fuzzy -#~| msgid "Search" -#~ msgctxt "abbrev. month" -#~ msgid "March" -#~ msgstr "Buscar" - -#, fuzzy -#~| msgid "Search" -#~ msgctxt "alt. month" -#~ msgid "March" -#~ msgstr "Buscar" - -#, fuzzy -#~| msgid "Series number:" -#~ msgctxt "alt. month" -#~ msgid "September" -#~ msgstr "Número de serie:" - -#, fuzzy -#~| msgid "No books found matching the query \"%(query)s\"" -#~ msgid "No %(verbose_name)s found matching the query" -#~ msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query)s\"" - #~ msgid "Announcements" #~ msgstr "Anuncios" From 903118417667a21fe687d56da2f4e2f5d0b5f1be Mon Sep 17 00:00:00 2001 From: Pablo Barton Date: Sat, 17 Apr 2021 21:31:38 -0400 Subject: [PATCH 004/109] addressing some review --- bookwyrm/templates/lists/list.html | 2 +- .../snippets/booklist-pagination.html | 64 +++++++++---------- bookwyrm/tests/views/test_list.py | 19 +++--- bookwyrm/views/list.py | 42 +++++++----- 4 files changed, 69 insertions(+), 58 deletions(-) diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index 3d3380977..c9464c85b 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -13,7 +13,6 @@
- {% include "snippets/booklist-pagination.html" with page=items %} {% if not items.object_list.exists %}

{% trans "This list is currently empty" %}

{% else %} @@ -58,6 +57,7 @@ {% endfor %} {% endif %} + {% include "snippets/booklist-pagination.html" with page=items %}
diff --git a/bookwyrm/templates/snippets/booklist-pagination.html b/bookwyrm/templates/snippets/booklist-pagination.html index 69fae52e8..161c743cb 100644 --- a/bookwyrm/templates/snippets/booklist-pagination.html +++ b/bookwyrm/templates/snippets/booklist-pagination.html @@ -1,6 +1,37 @@ {% load i18n %} {% if page.has_other_pages %} -
{% endif %} -
-
- {% if book.isbn_13 %} -
-
{% trans "ISBN:" %}
-
{{ book.isbn_13 }}
+
+ {% with book=book %} +
+ {% include 'book/publisher_info.html' %}
- {% endif %} - {% if book.oclc_number %} -
-
{% trans "OCLC Number:" %}
-
{{ book.oclc_number }}
+
+ {% include 'book/book_identifiers.html' %}
- {% endif %} - - {% if book.asin %} -
-
{% trans "ASIN:" %}
-
{{ book.asin }}
-
- {% endif %} -
- - {% include 'book/publisher_info.html' with book=book %} + {% endwith %} {% if book.openlibrary_key %}

{% trans "View on OpenLibrary" %}

diff --git a/bookwyrm/templates/book/book_identifiers.html b/bookwyrm/templates/book/book_identifiers.html new file mode 100644 index 000000000..d71ea4096 --- /dev/null +++ b/bookwyrm/templates/book/book_identifiers.html @@ -0,0 +1,27 @@ +{% spaceless %} + +{% load i18n %} + +
+ {% if book.isbn_13 %} +
+
{% trans "ISBN:" %}
+
{{ book.isbn_13 }}
+
+ {% endif %} + + {% if book.oclc_number %} +
+
{% trans "OCLC Number:" %}
+
{{ book.oclc_number }}
+
+ {% endif %} + + {% if book.asin %} +
+
{% trans "ASIN:" %}
+
{{ book.asin }}
+
+ {% endif %} +
+{% endspaceless %} diff --git a/bookwyrm/templates/book/editions.html b/bookwyrm/templates/book/editions.html index 91259465e..339e835f2 100644 --- a/bookwyrm/templates/book/editions.html +++ b/bookwyrm/templates/book/editions.html @@ -25,7 +25,18 @@ {{ book.title }} - {% include 'book/publisher_info.html' with book=book %} + + {% with book=book %} +
+
+ {% include 'book/publisher_info.html' %} +
+ +
+ {% include 'book/book_identifiers.html' %} +
+
+ {% endwith %}
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %} From 3d0de5bea8c367ebe47e38157f23abbc38532f5b Mon Sep 17 00:00:00 2001 From: Pablo Barton Date: Sun, 18 Apr 2021 11:15:42 -0400 Subject: [PATCH 007/109] approving list items puts them at the end of the list --- bookwyrm/views/list.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index a295806be..b5d8c6821 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -4,7 +4,7 @@ from django.core.paginator import Paginator from django.db import IntegrityError, transaction from django.db.models import Avg, Count, Q, Max from django.db.models.functions import Coalesce -from django.http import HttpResponseNotFound, HttpResponseBadRequest +from django.http import HttpResponseNotFound, HttpResponseBadRequest, HttpResponse from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.utils.decorators import method_decorator @@ -211,7 +211,13 @@ class Curate(View): approved = request.POST.get("approved") == "true" if approved: suggestion.approved = True + current_order = suggestion.order + order_max = ( + book_list.listitem_set.aggregate(Max("order"))["order__max"] or 0 + ) + 1 + suggestion.order = order_max suggestion.save() + normalize_book_list_ordering(book_list.id, start=current_order) else: deleted_order = suggestion.order suggestion.delete(broadcast=False) @@ -302,7 +308,7 @@ def set_book_position(request, list_item_id): original_order = list_item.order if original_order == int_position: - return + return HttpResponse(status=204) elif original_order > int_position: list_item.order = -1 list_item.save() From afd1cdc2a8296c630b0dca1f852a1975ed78fd33 Mon Sep 17 00:00:00 2001 From: Pablo Barton Date: Sun, 18 Apr 2021 11:52:22 -0400 Subject: [PATCH 008/109] adjust test --- bookwyrm/tests/views/test_list.py | 2 +- bookwyrm/views/list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py index a2bd0674c..02581939b 100644 --- a/bookwyrm/tests/views/test_list.py +++ b/bookwyrm/tests/views/test_list.py @@ -221,7 +221,7 @@ class ListViews(TestCase): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock: view(request, self.list.id) - self.assertEqual(mock.call_count, 1) + self.assertEqual(mock.call_count, 2) activity = json.loads(mock.call_args[0][1]) self.assertEqual(activity["type"], "Add") self.assertEqual(activity["actor"], self.local_user.remote_id) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index b5d8c6821..2f01410d2 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -357,7 +357,7 @@ def normalize_book_list_ordering(book_list_id, start=0, add_offset=0): try: book_list = models.List.objects.get(id=book_list_id) except models.List.DoesNotExist: - return + return HttpResponseNotFound() items = book_list.listitem_set.filter(order__gt=start).order_by("order") for i, item in enumerate(items, start): effective_order = i + add_offset From 7a2731aef4c7182875056b19b5f57bc4372bd502 Mon Sep 17 00:00:00 2001 From: D Anzorge Date: Sun, 18 Apr 2021 16:30:01 +0200 Subject: [PATCH 009/109] Use object ids with our instance base path for follow accept/reject --- bookwyrm/models/relationship.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py index 998d7bed5..927c87407 100644 --- a/bookwyrm/models/relationship.py +++ b/bookwyrm/models/relationship.py @@ -50,11 +50,10 @@ class UserRelationship(BookWyrmModel): ), ] - def get_remote_id(self, status=None): # pylint: disable=arguments-differ + def get_remote_id(self): """ use shelf identifier in remote_id """ - status = status or "follows" base_path = self.user_subject.remote_id - return "%s#%s/%d" % (base_path, status, self.id) + return "%s#follows/%d" % (base_path, self.id) class UserFollows(ActivityMixin, UserRelationship): @@ -138,12 +137,18 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship): notification_type=notification_type, ) + def get_accept_reject_id(self, status): + """ get id for sending an accept or reject of a local user """ + + base_path = self.user_object.remote_id + return "%s#%s/%d" % (base_path, status, self.id) + def accept(self): """ turn this request into the real deal""" user = self.user_object if not self.user_subject.local: activity = activitypub.Accept( - id=self.get_remote_id(status="accepts"), + id=self.get_accept_reject_id(status="accepts"), actor=self.user_object.remote_id, object=self.to_activity(), ).serialize() @@ -156,7 +161,7 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship): """ generate a Reject for this follow request """ if self.user_object.local: activity = activitypub.Reject( - id=self.get_remote_id(status="rejects"), + id=self.get_accept_reject_id(status="rejects"), actor=self.user_object.remote_id, object=self.to_activity(), ).serialize() From 415d6c4e3f485009b3803777fb633ed4215b56c4 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Sun, 18 Apr 2021 18:24:32 +0200 Subject: [PATCH 010/109] Remove spacing between publisher info blocks. --- bookwyrm/templates/book/editions.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/editions.html b/bookwyrm/templates/book/editions.html index 339e835f2..70f067f76 100644 --- a/bookwyrm/templates/book/editions.html +++ b/bookwyrm/templates/book/editions.html @@ -28,7 +28,7 @@ {% with book=book %}
-
+
{% include 'book/publisher_info.html' %}
From fa75438070e6b9e800eafe76a82d8737f972278b Mon Sep 17 00:00:00 2001 From: Pablo Barton Date: Sun, 18 Apr 2021 14:46:28 -0400 Subject: [PATCH 011/109] per review, removing custom pagination for booklist and handling all pending books at the end of the list --- bookwyrm/templates/lists/list.html | 2 +- .../snippets/booklist-pagination.html | 58 --------- bookwyrm/tests/views/test_list.py | 118 ++++++++++++++++++ bookwyrm/views/list.py | 49 +++++--- 4 files changed, 154 insertions(+), 73 deletions(-) delete mode 100644 bookwyrm/templates/snippets/booklist-pagination.html diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index c9464c85b..2f0e7d678 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -57,7 +57,7 @@ {% endfor %} {% endif %} - {% include "snippets/booklist-pagination.html" with page=items %} + {% include "snippets/pagination.html" with page=items %}
diff --git a/bookwyrm/templates/snippets/booklist-pagination.html b/bookwyrm/templates/snippets/booklist-pagination.html deleted file mode 100644 index 161c743cb..000000000 --- a/bookwyrm/templates/snippets/booklist-pagination.html +++ /dev/null @@ -1,58 +0,0 @@ -{% load i18n %} -{% if page.has_other_pages %} - -{% endif %} diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py index 02581939b..215f3e61e 100644 --- a/bookwyrm/tests/views/test_list.py +++ b/bookwyrm/tests/views/test_list.py @@ -51,6 +51,13 @@ class ListViews(TestCase): remote_id="https://example.com/book/3", parent_work=work_three, ) + work_four = models.Work.objects.create(title="Travailler") + self.book_four = models.Edition.objects.create( + title="Example Edition 4", + remote_id="https://example.com/book/4", + parent_work=work_four, + ) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): self.list = models.List.objects.create( name="Test List", user=self.local_user @@ -369,6 +376,117 @@ class ListViews(TestCase): self.assertEqual(items[0].order, 1) self.assertEqual(items[1].order, 2) + def test_adding_book_with_a_pending_book(self): + """ + When a list contains any pending books, the pending books should have + be at the end of the list by order. If a book is added while a book is + pending, its order should precede the pending books. + """ + request = self.factory.post( + "", + { + "book": self.book_three.id, + "list": self.list.id, + }, + ) + request.user = self.local_user + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + models.ListItem.objects.create( + book_list=self.list, + user=self.local_user, + book=self.book, + approved=True, + order=1, + ) + models.ListItem.objects.create( + book_list=self.list, + user=self.rat, + book=self.book_two, + approved=False, + order=2, + ) + views.list.add_book(request) + + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[0].order, 1) + self.assertTrue(items[0].approved) + + self.assertEqual(items[1].book, self.book_three) + self.assertEqual(items[1].order, 2) + self.assertTrue(items[1].approved) + + self.assertEqual(items[2].book, self.book_two) + self.assertEqual(items[2].order, 3) + self.assertFalse(items[2].approved) + + def test_approving_one_pending_book_from_multiple(self): + """ + When a list contains any pending books, the pending books should have + be at the end of the list by order. If a pending book is approved, then + its order should be at the end of the approved books and before the + remaining pending books. + """ + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + models.ListItem.objects.create( + book_list=self.list, + user=self.local_user, + book=self.book, + approved=True, + order=1, + ) + models.ListItem.objects.create( + book_list=self.list, + user=self.local_user, + book=self.book_two, + approved=True, + order=2, + ) + models.ListItem.objects.create( + book_list=self.list, + user=self.rat, + book=self.book_three, + approved=False, + order=3, + ) + to_be_approved = models.ListItem.objects.create( + book_list=self.list, + user=self.rat, + book=self.book_four, + approved=False, + order=4, + ) + + view = views.Curate.as_view() + request = self.factory.post( + "", + { + "item": to_be_approved.id, + "approved": "true", + }, + ) + request.user = self.local_user + + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + view(request, self.list.id) + + items = self.list.listitem_set.order_by("order").all() + self.assertEqual(items[0].book, self.book) + self.assertEqual(items[0].order, 1) + self.assertTrue(items[0].approved) + + self.assertEqual(items[1].book, self.book_two) + self.assertEqual(items[1].order, 2) + self.assertTrue(items[1].approved) + + self.assertEqual(items[2].book, self.book_four) + self.assertEqual(items[2].order, 3) + self.assertTrue(items[2].approved) + + self.assertEqual(items[3].book, self.book_three) + self.assertEqual(items[3].order, 4) + self.assertFalse(items[3].approved) + def test_add_three_books_and_move_last_to_first(self): """ Put three books on the list and move the last book to the first diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 2f01410d2..7fb4979cb 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -1,4 +1,6 @@ """ book list views""" +from typing import Optional + from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.db import IntegrityError, transaction @@ -140,7 +142,7 @@ class List(View): .order_by(directional_sort_by) ) - paginated = Paginator(items, 25) + paginated = Paginator(items, 12) if query and request.user.is_authenticated: # search for books @@ -210,14 +212,17 @@ class Curate(View): suggestion = get_object_or_404(models.ListItem, id=request.POST.get("item")) approved = request.POST.get("approved") == "true" if approved: + # update the book and set it to be the last in the order of approved books, before any pending books suggestion.approved = True - current_order = suggestion.order order_max = ( - book_list.listitem_set.aggregate(Max("order"))["order__max"] or 0 + book_list.listitem_set.filter(approved=True).aggregate(Max("order"))[ + "order__max" + ] + or 0 ) + 1 suggestion.order = order_max + increment_order_in_reverse(book_list.id, order_max) suggestion.save() - normalize_book_list_ordering(book_list.id, start=current_order) else: deleted_order = suggestion.order suggestion.delete(broadcast=False) @@ -232,13 +237,17 @@ def add_book(request): if not book_list.visible_to_user(request.user): return HttpResponseNotFound() - order_max = book_list.listitem_set.aggregate(Max("order"))["order__max"] or 0 - book = get_object_or_404(models.Edition, id=request.POST.get("book")) # do you have permission to add to the list? try: if request.user == book_list.user or book_list.curation == "open": - # go ahead and add it + # add the book at the latest order of approved books, before any pending books + order_max = ( + book_list.listitem_set.filter(approved=True).aggregate(Max("order"))[ + "order__max" + ] + ) or 0 + increment_order_in_reverse(book_list.id, order_max + 1) models.ListItem.objects.create( book=book, book_list=book_list, @@ -246,7 +255,10 @@ def add_book(request): order=order_max + 1, ) elif book_list.curation == "curated": - # make a pending entry + # make a pending entry at the end of the list + order_max = ( + book_list.listitem_set.aggregate(Max("order"))["order__max"] + ) or 0 models.ListItem.objects.create( approved=False, book=book, @@ -283,7 +295,8 @@ def remove_book(request, list_id): @require_POST def set_book_position(request, list_item_id): """ - Action for when the list user manually specifies a list position, takes special care with the unique ordering per list + Action for when the list user manually specifies a list position, takes + special care with the unique ordering per list. """ with transaction.atomic(): list_item = get_object_or_404(models.ListItem, id=list_item_id) @@ -298,7 +311,12 @@ def set_book_position(request, list_item_id): return HttpResponseBadRequest("position cannot be less than 1") book_list = list_item.book_list - order_max = book_list.listitem_set.aggregate(Max("order"))["order__max"] + + # the max position to which a book may be set is the highest order for + # books which are approved + order_max = book_list.listitem_set.filter(approved=True).aggregate( + Max("order") + )["order__max"] if int_position > order_max: int_position = order_max @@ -325,14 +343,17 @@ def set_book_position(request, list_item_id): @transaction.atomic -def increment_order_in_reverse(book_list_id, start, end): +def increment_order_in_reverse( + book_list_id: int, start: int, end: Optional[int] = None +): try: book_list = models.List.objects.get(id=book_list_id) except models.List.DoesNotExist: return - items = book_list.listitem_set.filter(order__gte=start, order__lt=end).order_by( - "-order" - ) + items = book_list.listitem_set.filter(order__gte=start) + if end is not None: + items = items.filter(order__lt=end) + items = items.order_by("-order") for item in items: item.order += 1 item.save() From 77775d9bf8133183d578eb51f89e35c102b81fc7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 14:47:59 -0700 Subject: [PATCH 012/109] Remove superfluous calls to `all()` --- bookwyrm/models/list.py | 2 +- bookwyrm/models/shelf.py | 2 +- bookwyrm/templatetags/bookwyrm_tags.py | 3 +-- bookwyrm/views/feed.py | 2 +- bookwyrm/views/list.py | 2 +- bookwyrm/views/shelf.py | 2 +- bookwyrm/views/user.py | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index 7e6de1069..639f84027 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -47,7 +47,7 @@ class List(OrderedCollectionMixin, BookWyrmModel): @property def collection_queryset(self): """ list of books for this shelf, overrides OrderedCollectionMixin """ - return self.books.filter(listitem__approved=True).all().order_by("listitem") + return self.books.filter(listitem__approved=True).order_by("listitem") class Meta: """ default sorting """ diff --git a/bookwyrm/models/shelf.py b/bookwyrm/models/shelf.py index 5bbb84b9b..d37668dd7 100644 --- a/bookwyrm/models/shelf.py +++ b/bookwyrm/models/shelf.py @@ -48,7 +48,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel): @property def collection_queryset(self): """ list of books for this shelf, overrides OrderedCollectionMixin """ - return self.books.all().order_by("shelfbook") + return self.books.order_by("shelfbook") def get_remote_id(self): """ shelf identifier instead of id """ diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 775c61903..bc526ba1b 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -67,8 +67,7 @@ def get_replies(status): reply_parent=status, deleted=False, ) - .select_subclasses() - .all()[:10] + .select_subclasses()[:10] ) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index cd2792823..1b66b494b 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -174,7 +174,7 @@ def get_suggested_books(user, max_books=5): ) shelf = user.shelf_set.get(identifier=preset) - shelf_books = shelf.shelfbook_set.order_by("-updated_date").all()[:limit] + shelf_books = shelf.shelfbook_set.order_by("-updated_date")[:limit] if not shelf_books: continue shelf_preview = { diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 7fb4979cb..ff20d9913 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -75,7 +75,7 @@ class UserLists(View): except ValueError: page = 1 user = get_user_from_username(request.user, username) - lists = models.List.objects.filter(user=user).all() + lists = models.List.objects.filter(user=user) lists = privacy_filter(request.user, lists) paginated = Paginator(lists, 12) diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index 740439db6..2ec9e69ff 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -61,7 +61,7 @@ class Shelf(View): return ActivitypubResponse(shelf.to_activity(**request.GET)) paginated = Paginator( - shelf.books.order_by("-updated_date").all(), + shelf.books.order_by("-updated_date"), PAGE_LENGTH, ) diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index 26117a928..e24db01ed 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -64,7 +64,7 @@ class User(View): { "name": user_shelf.name, "local_path": user_shelf.local_path, - "books": user_shelf.books.all()[:3], + "books": user_shelf.books[:3], "size": user_shelf.books.count(), } ) From 91aa6fa95f508713ddb8715dd8933b233bbc9b1e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:01:20 -0700 Subject: [PATCH 013/109] Remove unneeded page checking logic --- bookwyrm/views/books.py | 14 ++------------ bookwyrm/views/directory.py | 8 +------- bookwyrm/views/federation.py | 7 +------ bookwyrm/views/feed.py | 15 ++------------- bookwyrm/views/invite.py | 14 ++------------ bookwyrm/views/list.py | 29 +++++++++++------------------ bookwyrm/views/reading.py | 1 + bookwyrm/views/shelf.py | 7 +------ bookwyrm/views/user.py | 7 +------ bookwyrm/views/user_admin.py | 7 +------ 10 files changed, 23 insertions(+), 86 deletions(-) diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index c3ac4f492..2a47c0d2b 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -30,11 +30,6 @@ class Book(View): def get(self, request, book_id): """ info about a book """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - try: book = models.Book.objects.select_subclasses().get(id=book_id) except models.Book.DoesNotExist: @@ -60,7 +55,7 @@ class Book(View): paginated = Paginator( reviews.exclude(Q(content__isnull=True) | Q(content="")), PAGE_LENGTH ) - reviews_page = paginated.get_page(page) + reviews_page = paginated.get_page(request.GET.get("page")) user_tags = readthroughs = user_shelves = other_edition_shelves = [] if request.user.is_authenticated: @@ -266,11 +261,6 @@ class Editions(View): """ list of editions of a book """ work = get_object_or_404(models.Work, id=book_id) - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - if is_api_request(request): return ActivitypubResponse(work.to_edition_list(**request.GET)) filters = {} @@ -285,7 +275,7 @@ class Editions(View): paginated = Paginator(editions.filter(**filters).all(), PAGE_LENGTH) data = { - "editions": paginated.get_page(page), + "editions": paginated.get_page(request.GET.get("page")), "work": work, "languages": languages, "formats": set( diff --git a/bookwyrm/views/directory.py b/bookwyrm/views/directory.py index 2565f4ec5..7919dac08 100644 --- a/bookwyrm/views/directory.py +++ b/bookwyrm/views/directory.py @@ -15,12 +15,6 @@ class Directory(View): def get(self, request): """ lets see your cute faces """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - - # filters filters = {} software = request.GET.get("software") if not software or software == "bookwyrm": @@ -39,7 +33,7 @@ class Directory(View): paginated = Paginator(users, 12) data = { - "users": paginated.get_page(page), + "users": paginated.get_page(request.GET.get("page")), } return TemplateResponse(request, "directory/directory.html", data) diff --git a/bookwyrm/views/federation.py b/bookwyrm/views/federation.py index 8712c463c..1acacf8f3 100644 --- a/bookwyrm/views/federation.py +++ b/bookwyrm/views/federation.py @@ -24,11 +24,6 @@ class Federation(View): def get(self, request): """ list of servers """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - servers = models.FederatedServer.objects sort = request.GET.get("sort") @@ -40,7 +35,7 @@ class Federation(View): paginated = Paginator(servers, PAGE_LENGTH) data = { - "servers": paginated.get_page(page), + "servers": paginated.get_page(request.GET.get("page")), "sort": sort, "form": forms.ServerForm(), } diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 1b66b494b..118473d03 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -22,11 +22,6 @@ class Feed(View): def get(self, request, tab): """ user's homepage with activity feed """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - if not tab in STREAMS: tab = "home" @@ -39,7 +34,7 @@ class Feed(View): **feed_page_data(request.user), **{ "user": request.user, - "activities": paginated.get_page(page), + "activities": paginated.get_page(request.GET.get("page")), "suggested_users": suggested_users, "tab": tab, "goal_form": forms.GoalForm(), @@ -55,11 +50,6 @@ class DirectMessage(View): def get(self, request, username=None): """ like a feed but for dms only """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - # remove fancy subclasses of status, keep just good ol' notes queryset = models.Status.objects.filter( review__isnull=True, @@ -82,13 +72,12 @@ class DirectMessage(View): ).order_by("-published_date") paginated = Paginator(activities, PAGE_LENGTH) - activity_page = paginated.get_page(page) data = { **feed_page_data(request.user), **{ "user": request.user, "partner": user, - "activities": activity_page, + "activities": paginated.get_page(request.GET.get("page")), "path": "/direct-messages", }, } diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py index 03b31b7b5..cbb189b5d 100644 --- a/bookwyrm/views/invite.py +++ b/bookwyrm/views/invite.py @@ -30,11 +30,6 @@ class ManageInvites(View): def get(self, request): """ invite management page """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - paginated = Paginator( models.SiteInvite.objects.filter(user=request.user).order_by( "-created_date" @@ -43,7 +38,7 @@ class ManageInvites(View): ) data = { - "invites": paginated.get_page(page), + "invites": paginated.get_page(request.GET.get("page")), "form": forms.CreateInviteForm(), } return TemplateResponse(request, "settings/manage_invites.html", data) @@ -93,11 +88,6 @@ class ManageInviteRequests(View): def get(self, request): """ view a list of requests """ ignored = request.GET.get("ignored", False) - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - sort = request.GET.get("sort") sort_fields = [ "created_date", @@ -136,7 +126,7 @@ class ManageInviteRequests(View): data = { "ignored": ignored, "count": paginated.count, - "requests": paginated.get_page(page), + "requests": paginated.get_page(request.GET.get("page")), "sort": sort, } return TemplateResponse(request, "settings/manage_invite_requests.html", data) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index ff20d9913..a2cf7afe9 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -26,11 +26,6 @@ class Lists(View): def get(self, request): """ display a book list """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - # hide lists with no approved books lists = ( models.List.objects.annotate( @@ -47,7 +42,7 @@ class Lists(View): paginated = Paginator(lists, 12) data = { - "lists": paginated.get_page(page), + "lists": paginated.get_page(request.GET.get("page")), "list_form": forms.ListForm(), "path": "/list", } @@ -70,10 +65,6 @@ class UserLists(View): def get(self, request, username): """ display a book list """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 user = get_user_from_username(request.user, username) lists = models.List.objects.filter(user=user) lists = privacy_filter(request.user, lists) @@ -82,7 +73,7 @@ class UserLists(View): data = { "user": user, "is_self": request.user.id == user.id, - "lists": paginated.get_page(page), + "lists": paginated.get_page(request.GET.get("page")), "list_form": forms.ListForm(), "path": user.local_path + "/lists", } @@ -114,8 +105,6 @@ class List(View): if direction not in ("ascending", "descending"): direction = "ascending" - page = request.GET.get("page", 1) - internal_sort_by = { "order": "order", "title": "book__title", @@ -163,7 +152,7 @@ class List(View): data = { "list": book_list, - "items": paginated.get_page(page), + "items": paginated.get_page(request.GET.get("page")), "pending_count": book_list.listitem_set.filter(approved=False).count(), "suggested_books": suggestions, "list_form": forms.ListForm(instance=book_list), @@ -212,7 +201,8 @@ class Curate(View): suggestion = get_object_or_404(models.ListItem, id=request.POST.get("item")) approved = request.POST.get("approved") == "true" if approved: - # update the book and set it to be the last in the order of approved books, before any pending books + # update the book and set it to be the last in the order of approved books, + # before any pending books suggestion.approved = True order_max = ( book_list.listitem_set.filter(approved=True).aggregate(Max("order"))[ @@ -241,7 +231,7 @@ def add_book(request): # do you have permission to add to the list? try: if request.user == book_list.user or book_list.curation == "open": - # add the book at the latest order of approved books, before any pending books + # add the book at the latest order of approved books, before pending books order_max = ( book_list.listitem_set.filter(approved=True).aggregate(Max("order"))[ "order__max" @@ -327,7 +317,7 @@ def set_book_position(request, list_item_id): original_order = list_item.order if original_order == int_position: return HttpResponse(status=204) - elif original_order > int_position: + if original_order > int_position: list_item.order = -1 list_item.save() increment_order_in_reverse(book_list.id, int_position, original_order) @@ -346,6 +336,7 @@ def set_book_position(request, list_item_id): def increment_order_in_reverse( book_list_id: int, start: int, end: Optional[int] = None ): + """ increase the order nu,ber for every item in a list """ try: book_list = models.List.objects.get(id=book_list_id) except models.List.DoesNotExist: @@ -361,6 +352,7 @@ def increment_order_in_reverse( @transaction.atomic def decrement_order(book_list_id, start, end): + """ decrement the order value for every item in a list """ try: book_list = models.List.objects.get(id=book_list_id) except models.List.DoesNotExist: @@ -375,10 +367,11 @@ def decrement_order(book_list_id, start, end): @transaction.atomic def normalize_book_list_ordering(book_list_id, start=0, add_offset=0): + """ gives each book in a list the proper sequential order number """ try: book_list = models.List.objects.get(id=book_list_id) except models.List.DoesNotExist: - return HttpResponseNotFound() + return items = book_list.listitem_set.filter(order__gt=start).order_by("order") for i, item in enumerate(items, start): effective_order = i + add_offset diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py index b780dd2fd..f2d5b2c2d 100644 --- a/bookwyrm/views/reading.py +++ b/bookwyrm/views/reading.py @@ -145,6 +145,7 @@ def create_readthrough(request): def load_date_in_user_tz_as_utc(date_str: str, user: models.User) -> datetime: + """ ensures that data is stored consistently in the UTC timezone """ user_tz = dateutil.tz.gettz(user.preferred_timezone) start_date = dateutil.parser.parse(date_str, ignoretz=True) return start_date.replace(tzinfo=user_tz).astimezone(dateutil.tz.UTC) diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index 2ec9e69ff..446bedba1 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -30,11 +30,6 @@ class Shelf(View): except models.User.DoesNotExist: return HttpResponseNotFound() - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - shelves = privacy_filter(request.user, user.shelf_set) # get the shelf and make sure the logged in user should be able to see it @@ -70,7 +65,7 @@ class Shelf(View): "is_self": is_self, "shelves": shelves.all(), "shelf": shelf, - "books": paginated.get_page(page), + "books": paginated.get_page(request.GET.get("page")), } return TemplateResponse(request, "user/shelf.html", data) diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index e24db01ed..9c79a77c2 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -40,11 +40,6 @@ class User(View): return ActivitypubResponse(user.to_activity()) # otherwise we're at a UI view - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - shelf_preview = [] # only show other shelves that should be visible @@ -87,7 +82,7 @@ class User(View): "is_self": is_self, "shelves": shelf_preview, "shelf_count": shelves.count(), - "activities": paginated.get_page(page), + "activities": paginated.get_page(request.GET.get("page", 1)), "goal": goal, } diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index cc3ff8411..c0d097d7d 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -20,11 +20,6 @@ class UserAdmin(View): def get(self, request): """ list of users """ - try: - page = int(request.GET.get("page", 1)) - except ValueError: - page = 1 - filters = {} server = request.GET.get("server") if server: @@ -50,7 +45,7 @@ class UserAdmin(View): paginated = Paginator(users, PAGE_LENGTH) data = { - "users": paginated.get_page(page), + "users": paginated.get_page(request.GET.get("page")), "sort": sort, "server": server, } From 0947b79fb1e02d3aa2e4b686a25480a06e8b7bbb Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:06:33 -0700 Subject: [PATCH 014/109] Python formatting --- bookwyrm/templatetags/bookwyrm_tags.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index bc526ba1b..52054ada3 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -62,13 +62,10 @@ def get_notification_count(user): def get_replies(status): """ get all direct replies to a status """ # TODO: this limit could cause problems - return ( - models.Status.objects.filter( - reply_parent=status, - deleted=False, - ) - .select_subclasses()[:10] - ) + return models.Status.objects.filter( + reply_parent=status, + deleted=False, + ).select_subclasses()[:10] @register.filter(name="parent") From 788e282dce34b4f35e143376add194c9af41f7c9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:12:36 -0700 Subject: [PATCH 015/109] Moves user admin pages into their own directory --- bookwyrm/templates/moderation/reports.html | 2 +- .../templates/{settings => user_admin}/server_filter.html | 0 bookwyrm/templates/{settings => user_admin}/user_admin.html | 2 +- .../{settings => user_admin}/user_admin_filters.html | 4 ++-- .../templates/{settings => user_admin}/username_filter.html | 0 bookwyrm/views/user_admin.py | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename bookwyrm/templates/{settings => user_admin}/server_filter.html (100%) rename bookwyrm/templates/{settings => user_admin}/user_admin.html (97%) rename bookwyrm/templates/{settings => user_admin}/user_admin_filters.html (51%) rename bookwyrm/templates/{settings => user_admin}/username_filter.html (100%) diff --git a/bookwyrm/templates/moderation/reports.html b/bookwyrm/templates/moderation/reports.html index 72cadae5a..f9d9d99b6 100644 --- a/bookwyrm/templates/moderation/reports.html +++ b/bookwyrm/templates/moderation/reports.html @@ -30,7 +30,7 @@ -{% include 'settings/user_admin_filters.html' %} +{% include 'user_admin/user_admin_filters.html' %}
{% if not reports %} diff --git a/bookwyrm/templates/settings/server_filter.html b/bookwyrm/templates/user_admin/server_filter.html similarity index 100% rename from bookwyrm/templates/settings/server_filter.html rename to bookwyrm/templates/user_admin/server_filter.html diff --git a/bookwyrm/templates/settings/user_admin.html b/bookwyrm/templates/user_admin/user_admin.html similarity index 97% rename from bookwyrm/templates/settings/user_admin.html rename to bookwyrm/templates/user_admin/user_admin.html index a96d37f5b..554fbdd34 100644 --- a/bookwyrm/templates/settings/user_admin.html +++ b/bookwyrm/templates/user_admin/user_admin.html @@ -13,7 +13,7 @@ {% block panel %} -{% include 'settings/user_admin_filters.html' %} +{% include 'user_admin/user_admin_filters.html' %} diff --git a/bookwyrm/templates/settings/user_admin_filters.html b/bookwyrm/templates/user_admin/user_admin_filters.html similarity index 51% rename from bookwyrm/templates/settings/user_admin_filters.html rename to bookwyrm/templates/user_admin/user_admin_filters.html index a7b5c8aa4..57e017e5f 100644 --- a/bookwyrm/templates/settings/user_admin_filters.html +++ b/bookwyrm/templates/user_admin/user_admin_filters.html @@ -1,6 +1,6 @@ {% extends 'snippets/filters_panel/filters_panel.html' %} {% block filter_fields %} -{% include 'settings/server_filter.html' %} -{% include 'settings/username_filter.html' %} +{% include 'user_admin/server_filter.html' %} +{% include 'user_admin/username_filter.html' %} {% endblock %} diff --git a/bookwyrm/templates/settings/username_filter.html b/bookwyrm/templates/user_admin/username_filter.html similarity index 100% rename from bookwyrm/templates/settings/username_filter.html rename to bookwyrm/templates/user_admin/username_filter.html diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index cc3ff8411..8b4704d0f 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -54,4 +54,4 @@ class UserAdmin(View): "sort": sort, "server": server, } - return TemplateResponse(request, "settings/user_admin.html", data) + return TemplateResponse(request, "user_admin/user_admin.html", data) From 0dd8b339910708eaf82d342fc13ff39dd096705f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:19:55 -0700 Subject: [PATCH 016/109] Moves user admin templates into snippets --- bookwyrm/templates/moderation/report.html | 71 +------------------ bookwyrm/templates/user_admin/user.html | 19 +++++ bookwyrm/templates/user_admin/user_info.html | 56 +++++++++++++++ .../user_admin/user_moderation_actions.html | 17 +++++ 4 files changed, 94 insertions(+), 69 deletions(-) create mode 100644 bookwyrm/templates/user_admin/user.html create mode 100644 bookwyrm/templates/user_admin/user_info.html create mode 100644 bookwyrm/templates/user_admin/user_moderation_actions.html diff --git a/bookwyrm/templates/moderation/report.html b/bookwyrm/templates/moderation/report.html index 1cadd28d4..a078fe450 100644 --- a/bookwyrm/templates/moderation/report.html +++ b/bookwyrm/templates/moderation/report.html @@ -15,76 +15,9 @@ {% include 'moderation/report_preview.html' with report=report %} -
-
-

{% trans "User details" %}

-
- {% include 'user/user_preview.html' with user=report.user %} - {% if report.user.summary %} -
- {{ report.user.summary | to_markdown | safe }} -
- {% endif %} +{% include 'user_admin/user_info.html' with user=report.user %} -

{% trans "View user profile" %}

-
-
- {% if not report.user.local %} - {% with server=report.user.federated_server %} -
-

{% trans "Instance details" %}

-
- {% if server %} -
{{ server.server_name }}
-
-
-
{% trans "Software:" %}
-
{{ server.application_type }}
-
-
-
{% trans "Version:" %}
-
{{ server.application_version }}
-
-
-
{% trans "Status:" %}
-
{{ server.status }}
-
-
- {% if server.notes %} -
{% trans "Notes" %}
-
- {{ server.notes }} -
- {% endif %} - -

- {% trans "View instance" %} -

- {% else %} - {% trans "Not set" %} - {% endif %} -
-
- {% endwith %} - {% endif %} -
- -
-

{% trans "Actions" %}

-
-

- {% trans "Send direct message" %} -

- - {% csrf_token %} - {% if report.user.is_active %} - - {% else %} - - {% endif %} - -
-
+{% include 'user_admin/user_moderation_actions.html' with user=report.user %}

{% trans "Moderator Comments" %}

diff --git a/bookwyrm/templates/user_admin/user.html b/bookwyrm/templates/user_admin/user.html new file mode 100644 index 000000000..7bb6abfa2 --- /dev/null +++ b/bookwyrm/templates/user_admin/user.html @@ -0,0 +1,19 @@ +{% extends 'settings/admin_layout.html' %} +{% load i18n %} +{% load bookwyrm_tags %} +{% load humanize %} + +{% block title %}{{ username }}{% endblock %} +{% block header %}{{ username }}{% endblock %} + +{% block panel %} + + +{% include 'user_admin/user_info.html' with user=user %} + +{% include 'user_admin/user_moderation_actions.html' with user=user %} + +{% endblock %} + diff --git a/bookwyrm/templates/user_admin/user_info.html b/bookwyrm/templates/user_admin/user_info.html new file mode 100644 index 000000000..e5f5d5806 --- /dev/null +++ b/bookwyrm/templates/user_admin/user_info.html @@ -0,0 +1,56 @@ +{% load i18n %} +{% load bookwyrm_tags %} +
+
+

{% trans "User details" %}

+
+ {% include 'user/user_preview.html' with user=user %} + {% if user.summary %} +
+ {{ user.summary | to_markdown | safe }} +
+ {% endif %} + +

{% trans "View user profile" %}

+
+
+ {% if not user.local %} + {% with server=user.federated_server %} +
+

{% trans "Instance details" %}

+
+ {% if server %} +
{{ server.server_name }}
+
+
+
{% trans "Software:" %}
+
{{ server.application_type }}
+
+
+
{% trans "Version:" %}
+
{{ server.application_version }}
+
+
+
{% trans "Status:" %}
+
{{ server.status }}
+
+
+ {% if server.notes %} +
{% trans "Notes" %}
+
+ {{ server.notes }} +
+ {% endif %} + +

+ {% trans "View instance" %} +

+ {% else %} + {% trans "Not set" %} + {% endif %} +
+
+ {% endwith %} + {% endif %} +
+ diff --git a/bookwyrm/templates/user_admin/user_moderation_actions.html b/bookwyrm/templates/user_admin/user_moderation_actions.html new file mode 100644 index 000000000..41010994e --- /dev/null +++ b/bookwyrm/templates/user_admin/user_moderation_actions.html @@ -0,0 +1,17 @@ +{% load i18n %} +
+

{% trans "Actions" %}

+
+

+ {% trans "Send direct message" %} +

+
+ {% csrf_token %} + {% if user.is_active %} + + {% else %} + + {% endif %} + +
+
From 1542866b6c9e07393ca03067c27475a807155f90 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:40:51 -0700 Subject: [PATCH 017/109] Adds user admin view --- bookwyrm/templates/user_admin/user.html | 2 +- bookwyrm/templates/user_admin/user_admin.html | 2 +- .../user_admin/user_moderation_actions.html | 2 +- bookwyrm/urls.py | 13 ++++++++++--- bookwyrm/views/__init__.py | 2 +- bookwyrm/views/user_admin.py | 16 +++++++++++++++- 6 files changed, 29 insertions(+), 8 deletions(-) diff --git a/bookwyrm/templates/user_admin/user.html b/bookwyrm/templates/user_admin/user.html index 7bb6abfa2..a33c71102 100644 --- a/bookwyrm/templates/user_admin/user.html +++ b/bookwyrm/templates/user_admin/user.html @@ -8,7 +8,7 @@ {% block panel %} {% include 'user_admin/user_info.html' with user=user %} diff --git a/bookwyrm/templates/user_admin/user_admin.html b/bookwyrm/templates/user_admin/user_admin.html index 554fbdd34..2ab526a9f 100644 --- a/bookwyrm/templates/user_admin/user_admin.html +++ b/bookwyrm/templates/user_admin/user_admin.html @@ -41,7 +41,7 @@
{% for user in users %} - + diff --git a/bookwyrm/templates/user_admin/user_moderation_actions.html b/bookwyrm/templates/user_admin/user_moderation_actions.html index 41010994e..043ef3863 100644 --- a/bookwyrm/templates/user_admin/user_moderation_actions.html +++ b/bookwyrm/templates/user_admin/user_moderation_actions.html @@ -5,7 +5,7 @@

{% trans "Send direct message" %}

- + {% csrf_token %} {% if user.is_active %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 9e280f3e2..5768ee019 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -51,13 +51,20 @@ urlpatterns = [ r"^password-reset/(?P[A-Za-z0-9]+)/?$", views.PasswordReset.as_view() ), # admin - re_path(r"^settings/site-settings", views.Site.as_view(), name="settings-site"), + re_path(r"^settings/site-settings/?$", views.Site.as_view(), name="settings-site"), re_path( - r"^settings/email-preview", + r"^settings/email-preview/?$", views.site.email_preview, name="settings-email-preview", ), - re_path(r"^settings/users", views.UserAdmin.as_view(), name="settings-users"), + re_path( + r"^settings/users/?$", views.UserAdminList.as_view(), name="settings-users" + ), + re_path( + r"^settings/users/(?P\d+)/?$", + views.UserAdmin.as_view(), + name="settings-user" + ), re_path( r"^settings/federation/?$", views.Federation.as_view(), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 9f8463b40..7714bbda1 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -37,5 +37,5 @@ from .status import CreateStatus, DeleteStatus, DeleteAndRedraft from .tag import Tag, AddTag, RemoveTag from .updates import get_notification_count, get_unread_status_count from .user import User, EditUser, Followers, Following -from .user_admin import UserAdmin +from .user_admin import UserAdmin, UserAdminList from .wellknown import * diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index 8b4704d0f..895c14641 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -1,6 +1,7 @@ """ manage user """ from django.contrib.auth.decorators import login_required, permission_required from django.core.paginator import Paginator +from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views import View @@ -15,7 +16,7 @@ from bookwyrm.settings import PAGE_LENGTH permission_required("bookwyrm.moderate_users", raise_exception=True), name="dispatch", ) -class UserAdmin(View): +class UserAdminList(View): """ admin view of users on this server """ def get(self, request): @@ -55,3 +56,16 @@ class UserAdmin(View): "server": server, } return TemplateResponse(request, "user_admin/user_admin.html", data) + +@method_decorator(login_required, name="dispatch") +@method_decorator( + permission_required("bookwyrm.moderate_users", raise_exception=True), + name="dispatch", +) +class UserAdmin(View): + """ moderate an individual user """ + + def get(self, request, user): + """ user view """ + user = get_object_or_404(models.User, id=user) + return TemplateResponse(request, "user_admin/user.html", {"user": user}) From da19089d34ffb374b8c09a0f2c0917e722aa7dbe Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 15:51:39 -0700 Subject: [PATCH 018/109] Changes language from "deactivate" to "suspend" --- .../templates/user_admin/user_moderation_actions.html | 6 +++--- bookwyrm/urls.py | 8 ++++---- bookwyrm/views/__init__.py | 2 +- bookwyrm/views/reports.py | 11 ++++++----- bookwyrm/views/user_admin.py | 1 + 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/bookwyrm/templates/user_admin/user_moderation_actions.html b/bookwyrm/templates/user_admin/user_moderation_actions.html index 043ef3863..311cbb4b5 100644 --- a/bookwyrm/templates/user_admin/user_moderation_actions.html +++ b/bookwyrm/templates/user_admin/user_moderation_actions.html @@ -5,12 +5,12 @@

{% trans "Send direct message" %}

- + {% csrf_token %} {% if user.is_active %} - + {% else %} - + {% endif %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 5768ee019..8c5266a6e 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -63,7 +63,7 @@ urlpatterns = [ re_path( r"^settings/users/(?P\d+)/?$", views.UserAdmin.as_view(), - name="settings-user" + name="settings-user", ), re_path( r"^settings/federation/?$", @@ -120,9 +120,9 @@ urlpatterns = [ name="settings-report", ), re_path( - r"^settings/reports/(?P\d+)/deactivate/?$", - views.deactivate_user, - name="settings-report-deactivate", + r"^settings/reports/(?P\d+)/suspend/?$", + views.suspend_user, + name="settings-report-suspend", ), re_path( r"^settings/reports/(?P\d+)/resolve/?$", diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 7714bbda1..c0f35ba81 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -25,7 +25,7 @@ from .notifications import Notifications from .outbox import Outbox from .reading import edit_readthrough, create_readthrough, delete_readthrough from .reading import start_reading, finish_reading, delete_progressupdate -from .reports import Report, Reports, make_report, resolve_report, deactivate_user +from .reports import Report, Reports, make_report, resolve_report, suspend_user from .rss_feed import RssFeed from .password import PasswordResetRequest, PasswordReset, ChangePassword from .search import Search diff --git a/bookwyrm/views/reports.py b/bookwyrm/views/reports.py index 3dd53cb96..07eb9b975 100644 --- a/bookwyrm/views/reports.py +++ b/bookwyrm/views/reports.py @@ -74,12 +74,13 @@ class Report(View): @login_required @permission_required("bookwyrm_moderate_user") -def deactivate_user(_, report_id): +def suspend_user(_, user_id): """ mark an account as inactive """ - report = get_object_or_404(models.Report, id=report_id) - report.user.is_active = not report.user.is_active - report.user.save() - return redirect("settings-report", report.id) + user = get_object_or_404(models.User, id=user_id) + user.is_active = not user.is_active + # this isn't a full deletion, so we don't want to tell the world + user.save(broadcast=False) + return redirect("settings-user", user.id) @login_required diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index 895c14641..0aea74ede 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -57,6 +57,7 @@ class UserAdminList(View): } return TemplateResponse(request, "user_admin/user_admin.html", data) + @method_decorator(login_required, name="dispatch") @method_decorator( permission_required("bookwyrm.moderate_users", raise_exception=True), From 35cb3fa8fce6644a7653edc43e980bffeb71df69 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 16:08:01 -0700 Subject: [PATCH 019/109] Updates tests --- bookwyrm/templates/user_admin/user.html | 4 ++-- bookwyrm/tests/views/test_reports.py | 10 +++------- bookwyrm/tests/views/test_user_admin.py | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/bookwyrm/templates/user_admin/user.html b/bookwyrm/templates/user_admin/user.html index a33c71102..463906501 100644 --- a/bookwyrm/templates/user_admin/user.html +++ b/bookwyrm/templates/user_admin/user.html @@ -3,8 +3,8 @@ {% load bookwyrm_tags %} {% load humanize %} -{% block title %}{{ username }}{% endblock %} -{% block header %}{{ username }}{% endblock %} +{% block title %}{{ user.username }}{% endblock %} +{% block header %}{{ user.username }}{% endblock %} {% block panel %}
diff --git a/bookwyrm/tests/views/test_reports.py b/bookwyrm/tests/views/test_reports.py index 1c56067ad..55f815707 100644 --- a/bookwyrm/tests/views/test_reports.py +++ b/bookwyrm/tests/views/test_reports.py @@ -1,5 +1,4 @@ """ test for app action functionality """ -from unittest.mock import patch from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory @@ -115,22 +114,19 @@ class ReportViews(TestCase): report.refresh_from_db() self.assertFalse(report.resolved) - def test_deactivate_user(self): + def test_suspend_user(self): """ toggle whether a user is able to log in """ self.assertTrue(self.rat.is_active) - report = models.Report.objects.create(reporter=self.local_user, user=self.rat) request = self.factory.post("") request.user = self.local_user request.user.is_superuser = True # de-activate - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - views.deactivate_user(request, report.id) + views.suspend_user(request, self.local_user.id) self.rat.refresh_from_db() self.assertFalse(self.rat.is_active) # re-activate - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - views.deactivate_user(request, report.id) + views.suspend_user(request, self.local_user.id) self.rat.refresh_from_db() self.assertTrue(self.rat.is_active) diff --git a/bookwyrm/tests/views/test_user_admin.py b/bookwyrm/tests/views/test_user_admin.py index dd20c1b64..4bb838123 100644 --- a/bookwyrm/tests/views/test_user_admin.py +++ b/bookwyrm/tests/views/test_user_admin.py @@ -21,9 +21,9 @@ class UserAdminViews(TestCase): ) models.SiteSettings.objects.create() - def test_user_admin_page(self): + def test_user_admin_list_page(self): """ there are so many views, this just makes sure it LOADS """ - view = views.UserAdmin.as_view() + view = views.UserAdminList.as_view() request = self.factory.get("") request.user = self.local_user request.user.is_superuser = True @@ -31,3 +31,14 @@ class UserAdminViews(TestCase): self.assertIsInstance(result, TemplateResponse) result.render() self.assertEqual(result.status_code, 200) + + def test_user_admin_page(self): + """ there are so many views, this just makes sure it LOADS """ + view = views.UserAdmin.as_view() + request = self.factory.get("") + request.user = self.local_user + request.user.is_superuser = True + result = view(request, self.local_user) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) From 70a819951ef922c97d4a3f23ff8e970404e07b44 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 16:18:29 -0700 Subject: [PATCH 020/109] Fixes localization weirdness with dates --- bookwyrm/templates/book/publisher_info.html | 2 +- .../snippets/status/status_body.html | 2 +- bookwyrm/templatetags/bookwyrm_tags.py | 22 ------------------- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/bookwyrm/templates/book/publisher_info.html b/bookwyrm/templates/book/publisher_info.html index a16332c5d..ca9265c50 100644 --- a/bookwyrm/templates/book/publisher_info.html +++ b/bookwyrm/templates/book/publisher_info.html @@ -39,7 +39,7 @@ {% endif %}

- {% with date=book.published_date|date:'M jS Y' publisher=book.publishers|join:', ' %} + {% with date=book.published_date|date:'M j Y' publisher=book.publishers|join:', ' %} {% if date or book.first_published_date %}

{% if not moderation_mode %}
- {{ related_status.published_date | post_date }} + {{ related_status.published_date|timesince }} {% include 'snippets/privacy-icons.html' with item=related_status %}
diff --git a/bookwyrm/tests/test_templatetags.py b/bookwyrm/tests/test_templatetags.py index b4dc517f1..2fadb978b 100644 --- a/bookwyrm/tests/test_templatetags.py +++ b/bookwyrm/tests/test_templatetags.py @@ -181,36 +181,6 @@ class TemplateTags(TestCase): uuid = bookwyrm_tags.get_uuid("hi") self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid)) - def test_time_since(self, _): - """ ultraconcise timestamps """ - self.assertEqual(bookwyrm_tags.time_since("bleh"), "") - - now = timezone.now() - self.assertEqual(bookwyrm_tags.time_since(now), "0s") - - seconds_ago = now - relativedelta(seconds=4) - self.assertEqual(bookwyrm_tags.time_since(seconds_ago), "4s") - - minutes_ago = now - relativedelta(minutes=8) - self.assertEqual(bookwyrm_tags.time_since(minutes_ago), "8m") - - hours_ago = now - relativedelta(hours=9) - self.assertEqual(bookwyrm_tags.time_since(hours_ago), "9h") - - days_ago = now - relativedelta(days=3) - self.assertEqual(bookwyrm_tags.time_since(days_ago), "3d") - - # I am not going to figure out how to mock dates tonight. - months_ago = now - relativedelta(months=5) - self.assertTrue( - re.match(r"[A-Z][a-z]{2} \d?\d", bookwyrm_tags.time_since(months_ago)) - ) - - years_ago = now - relativedelta(years=10) - self.assertTrue( - re.match(r"[A-Z][a-z]{2} \d?\d \d{4}", bookwyrm_tags.time_since(years_ago)) - ) - def test_get_markdown(self, _): """ mardown format data """ result = bookwyrm_tags.get_markdown("_hi_") From e1d24577d458ad883cac49ee4543537eae5971e9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 16:42:51 -0700 Subject: [PATCH 023/109] Fixes tests (again) --- bookwyrm/tests/views/test_reports.py | 4 ++-- bookwyrm/tests/views/test_user_admin.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/views/test_reports.py b/bookwyrm/tests/views/test_reports.py index 55f815707..bce19993d 100644 --- a/bookwyrm/tests/views/test_reports.py +++ b/bookwyrm/tests/views/test_reports.py @@ -122,11 +122,11 @@ class ReportViews(TestCase): request.user.is_superuser = True # de-activate - views.suspend_user(request, self.local_user.id) + views.suspend_user(request, self.rat.id) self.rat.refresh_from_db() self.assertFalse(self.rat.is_active) # re-activate - views.suspend_user(request, self.local_user.id) + views.suspend_user(request, self.rat.id) self.rat.refresh_from_db() self.assertTrue(self.rat.is_active) diff --git a/bookwyrm/tests/views/test_user_admin.py b/bookwyrm/tests/views/test_user_admin.py index 4bb838123..1884d0002 100644 --- a/bookwyrm/tests/views/test_user_admin.py +++ b/bookwyrm/tests/views/test_user_admin.py @@ -38,7 +38,9 @@ class UserAdminViews(TestCase): request = self.factory.get("") request.user = self.local_user request.user.is_superuser = True - result = view(request, self.local_user) + + result = view(request, self.local_user.id) + self.assertIsInstance(result, TemplateResponse) result.render() self.assertEqual(result.status_code, 200) From 0a37b4665ca19f8bf9d722e51e1c9a4559e5bb3f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 17:16:14 -0700 Subject: [PATCH 024/109] Adds control for moderator to set user group --- bookwyrm/forms.py | 5 ++++ .../user_admin/user_moderation_actions.html | 25 +++++++++++++++++++ bookwyrm/views/user_admin.py | 14 +++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 80b283109..ac5bd0273 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -149,6 +149,11 @@ class LimitedEditUserForm(CustomForm): ] help_texts = {f: None for f in fields} +class UserGroupForm(CustomForm): + class Meta: + model = models.User + fields = ["groups"] + class TagForm(CustomForm): class Meta: diff --git a/bookwyrm/templates/user_admin/user_moderation_actions.html b/bookwyrm/templates/user_admin/user_moderation_actions.html index 311cbb4b5..816e787a2 100644 --- a/bookwyrm/templates/user_admin/user_moderation_actions.html +++ b/bookwyrm/templates/user_admin/user_moderation_actions.html @@ -14,4 +14,29 @@ {% endif %} + {% if user.local %} +
+
+ {% csrf_token %} + + {% if group_form.non_field_errors %} + {{ group_form.non_field_errors }} + {% endif %} + {% with group=user.groups.first %} +
+ +
+ {% for error in group_form.groups.errors %} +

{{ error | escape }}

+ {% endfor %} + {% endwith %} + + +
+ {% endif %} diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index 0aea74ede..3ea7016a5 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -6,7 +6,7 @@ from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views import View -from bookwyrm import models +from bookwyrm import forms, models from bookwyrm.settings import PAGE_LENGTH @@ -69,4 +69,14 @@ class UserAdmin(View): def get(self, request, user): """ user view """ user = get_object_or_404(models.User, id=user) - return TemplateResponse(request, "user_admin/user.html", {"user": user}) + data = {"user": user, "group_form": forms.UserGroupForm()} + return TemplateResponse(request, "user_admin/user.html", data) + + def post(self, request, user): + """ update user group """ + user = get_object_or_404(models.User, id=user) + form = forms.UserGroupForm(request.POST, instance=user) + if form.is_valid(): + form.save() + data = {"user": user, "group_form": form} + return TemplateResponse(request, "user_admin/user.html", data) From 63509c954da2192058abb2cfcb88f9009fcbc9fc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 18:12:55 -0700 Subject: [PATCH 025/109] Adds test for changing user group --- bookwyrm/forms.py | 1 + bookwyrm/tests/views/test_user_admin.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index ac5bd0273..1f1f1a3b5 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -149,6 +149,7 @@ class LimitedEditUserForm(CustomForm): ] help_texts = {f: None for f in fields} + class UserGroupForm(CustomForm): class Meta: model = models.User diff --git a/bookwyrm/tests/views/test_user_admin.py b/bookwyrm/tests/views/test_user_admin.py index 1884d0002..4e1e106d9 100644 --- a/bookwyrm/tests/views/test_user_admin.py +++ b/bookwyrm/tests/views/test_user_admin.py @@ -1,4 +1,5 @@ """ test for app action functionality """ +from django.contrib.auth.models import Group from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory @@ -44,3 +45,24 @@ class UserAdminViews(TestCase): self.assertIsInstance(result, TemplateResponse) result.render() self.assertEqual(result.status_code, 200) + + def test_user_admin_page_post(self): + """ set the user's group """ + group = Group.objects.create(name="editor") + self.assertEqual( + list(self.local_user.groups.values_list("name", flat=True)), [] + ) + + view = views.UserAdmin.as_view() + request = self.factory.post("", {"groups": [group.id]}) + request.user = self.local_user + request.user.is_superuser = True + + result = view(request, self.local_user.id) + + self.assertIsInstance(result, TemplateResponse) + result.render() + + self.assertEqual( + list(self.local_user.groups.values_list("name", flat=True)), ["editor"] + ) From 2c013b677bb8a947840f1a7de38803cff1badcc1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 19 Apr 2021 20:01:29 -0700 Subject: [PATCH 026/109] Patch broadcast in test --- bookwyrm/tests/views/test_user_admin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_user_admin.py b/bookwyrm/tests/views/test_user_admin.py index 4e1e106d9..b1e9d6394 100644 --- a/bookwyrm/tests/views/test_user_admin.py +++ b/bookwyrm/tests/views/test_user_admin.py @@ -1,4 +1,5 @@ """ test for app action functionality """ +from unittest.mock import patch from django.contrib.auth.models import Group from django.template.response import TemplateResponse from django.test import TestCase @@ -58,7 +59,8 @@ class UserAdminViews(TestCase): request.user = self.local_user request.user.is_superuser = True - result = view(request, self.local_user.id) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + result = view(request, self.local_user.id) self.assertIsInstance(result, TemplateResponse) result.render() From 978760475f5140f61f8f3dd7c3a7a0b454fa412c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 09:54:02 -0700 Subject: [PATCH 027/109] More compact display of statuses --- .../snippets/status/book_preview.html | 14 -- .../snippets/status/content_status.html | 126 ++++++++++++++++ .../snippets/status/generated_status.html | 43 ++++++ .../templates/snippets/status/layout.html | 86 +++++++++++ .../snippets/status/status_body.html | 89 +----------- .../snippets/status/status_content.html | 137 ------------------ 6 files changed, 261 insertions(+), 234 deletions(-) delete mode 100644 bookwyrm/templates/snippets/status/book_preview.html create mode 100644 bookwyrm/templates/snippets/status/content_status.html create mode 100644 bookwyrm/templates/snippets/status/generated_status.html create mode 100644 bookwyrm/templates/snippets/status/layout.html delete mode 100644 bookwyrm/templates/snippets/status/status_content.html diff --git a/bookwyrm/templates/snippets/status/book_preview.html b/bookwyrm/templates/snippets/status/book_preview.html deleted file mode 100644 index 920b9f538..000000000 --- a/bookwyrm/templates/snippets/status/book_preview.html +++ /dev/null @@ -1,14 +0,0 @@ -{% load bookwyrm_tags %} -
-
-
- {% include 'snippets/book_cover.html' with book=book %} - {% include 'snippets/stars.html' with rating=book|rating:request.user %} - {% include 'snippets/shelve_button/shelve_button.html' with book=book %} -
-
-
-

{% include 'snippets/book_titleby.html' with book=book %}

- {% include 'snippets/trimmed_text.html' with full=book|book_description %} -
-
diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html new file mode 100644 index 000000000..05662098c --- /dev/null +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -0,0 +1,126 @@ +{% spaceless %} + +{% load bookwyrm_tags %} +{% load i18n %} + +{% with status_type=status.status_type %} +
+ +
+ {% if not hide_book %} + {% with book=status.book|default:status.mention_books.first %} +
+
+ {% include 'snippets/book_cover.html' with book=book %} + {% include 'snippets/stars.html' with rating=book|rating:request.user %} + {% include 'snippets/shelve_button/shelve_button.html' with book=book %} +
+
+ {% endwith %} + {% endif %} + +
+ {% if status_type == 'Review' %} +
+

+ {{ status.name|escape }} +

+ +

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

+
+ {% endif %} + + {% if status.content_warning %} +
+

{{ status.content_warning }}

+ + {% trans "Show more" as button_text %} + + {% with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %} + {% include 'snippets/toggle/open_button.html' %} + {% endwith %} +
+ {% endif %} + + +
+
+ +{% endwith %} +{% endspaceless %} diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html new file mode 100644 index 000000000..f4186cd10 --- /dev/null +++ b/bookwyrm/templates/snippets/status/generated_status.html @@ -0,0 +1,43 @@ +{% spaceless %} + +{% load bookwyrm_tags %} +{% load i18n %} + +{% if status_type == 'Rating' %} +
+
+ + + + {# @todo Is it possible to not hard-code the value? #} + + + + {% include 'snippets/stars.html' with rating=status.rating %} +
+
+{% endif %} + +{% if not hide_book %} +{% with book=status.book|default:status.mention_books.first %} +
+ +
+

{% include 'snippets/book_titleby.html' with book=book %}

+

{{ book|book_description|default:""|truncatewords_html:20 }}

+ {% include 'snippets/shelve_button/shelve_button.html' with book=book %} +
+
+{% endwith %} +{% endif %} + +{% endspaceless %} diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html new file mode 100644 index 000000000..5b6c0c78d --- /dev/null +++ b/bookwyrm/templates/snippets/status/layout.html @@ -0,0 +1,86 @@ +{% extends 'components/card.html' %} +{% load i18n %} + +{% load bookwyrm_tags %} +{% load humanize %} + +{% block card-header %} +

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

+{% endblock %} + +{% block card-content %}{% endblock %} + +{% block card-footer %} + + + + + +{% if not moderation_mode %} + +{% endif %} +{% endblock %} + + +{% block card-bonus %} +{% if request.user.is_authenticated and not moderation_mode %} +{% with status.id|uuid as uuid %} + +{% endwith %} +{% endif %} +{% endblock %} diff --git a/bookwyrm/templates/snippets/status/status_body.html b/bookwyrm/templates/snippets/status/status_body.html index ffa71d5e1..58d3fbf4e 100644 --- a/bookwyrm/templates/snippets/status/status_body.html +++ b/bookwyrm/templates/snippets/status/status_body.html @@ -1,90 +1,13 @@ -{% extends 'components/card.html' %} -{% load i18n %} - -{% load bookwyrm_tags %} -{% load humanize %} - -{% block card-header %} -

- {% include 'snippets/status/status_header.html' with status=status %} -

-{% endblock %} - +{% extends 'snippets/status/layout.html' %} {% block card-content %} - {% include 'snippets/status/status_content.html' with status=status %} -{% endblock %} +{% with status_type=status.status_type %} - -{% block card-footer %} - - - - - -{% if not moderation_mode %} - +{% if status_type == 'GeneratedNote' or status_type == 'Rating' %} + {% include 'snippets/status/generated_status.html' with status=status %} +{% else %} + {% include 'snippets/status/content_status.html' with status=status %} {% endif %} -{% endblock %} - -{% block card-bonus %} -{% if request.user.is_authenticated and not moderation_mode %} -{% with status.id|uuid as uuid %} - {% endwith %} -{% endif %} {% endblock %} diff --git a/bookwyrm/templates/snippets/status/status_content.html b/bookwyrm/templates/snippets/status/status_content.html deleted file mode 100644 index 402c4aabd..000000000 --- a/bookwyrm/templates/snippets/status/status_content.html +++ /dev/null @@ -1,137 +0,0 @@ -{% spaceless %} - -{% load bookwyrm_tags %} -{% load i18n %} - -{% with status_type=status.status_type %} -
- {% if status_type == 'Review' or status_type == 'Rating' %} -
- {% if status.name %} -

- {{ status.name|escape }} -

- {% endif %} - - - - - {% if status_type == 'Rating' %} - {# @todo Is it possible to not hard-code the value? #} - - {% endif %} - - - {% include 'snippets/stars.html' with rating=status.rating %} -
- {% endif %} - - {% if status.content_warning %} -
-

{{ status.content_warning }}

- - {% trans "Show more" as button_text %} - - {% with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %} - {% include 'snippets/toggle/open_button.html' %} - {% endwith %} -
- {% endif %} - - -
- -{% if not hide_book %} - {% if status.book or status.mention_books.count %} -
- {% if status.book %} - {% with book=status.book %} - {% include 'snippets/status/book_preview.html' %} - {% endwith %} - {% elif status.mention_books.count %} - {% with book=status.mention_books.first %} - {% include 'snippets/status/book_preview.html' %} - {% endwith %} - {% endif %} -
- {% endif %} -{% endif %} -{% endwith %} -{% endspaceless %} From 07dbc4c6c042d9ce5b96106dd2f366d8c295d7a0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 09:56:01 -0700 Subject: [PATCH 028/109] Much longer "full" version of trimmed text --- bookwyrm/templates/snippets/trimmed_text.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index e1728b8f6..31c72eca3 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -5,7 +5,7 @@ {% with 0|uuid as uuid %} {% if full %} {% with full|to_markdown|safe as full %} - {% with full|to_markdown|safe|truncatewords_html:60 as trimmed %} + {% with full|to_markdown|safe|truncatewords_html:150 as trimmed %} {% if not no_trim and trimmed != full %}
From 9e5ebf9807b58b1eb4cd160e8071933fa0b7ea1b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 11:06:14 -0700 Subject: [PATCH 029/109] Move stars into header for ratings --- bookwyrm/templates/snippets/stars.html | 4 +- .../snippets/status/content_status.html | 190 +++++++++--------- .../snippets/status/generated_status.html | 22 +- .../snippets/status/status_header.html | 23 ++- 4 files changed, 120 insertions(+), 119 deletions(-) diff --git a/bookwyrm/templates/snippets/stars.html b/bookwyrm/templates/snippets/stars.html index 2b40a9e3c..ac049f254 100644 --- a/bookwyrm/templates/snippets/stars.html +++ b/bookwyrm/templates/snippets/stars.html @@ -1,7 +1,7 @@ {% spaceless %} {% load i18n %} -

+ {% if rating %} {% blocktranslate trimmed with rating=rating|floatformat count counter=rating|length %} @@ -23,5 +23,5 @@ aria-hidden="true" > {% endfor %} -

+ {% endspaceless %} diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html index 05662098c..44c52c836 100644 --- a/bookwyrm/templates/snippets/status/content_status.html +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -6,120 +6,122 @@ {% with status_type=status.status_type %}
- {% if not hide_book %} - {% with book=status.book|default:status.mention_books.first %} -
-
+ {% if not hide_book %} + {% with book=status.book|default:status.mention_books.first %} +
{% include 'snippets/book_cover.html' with book=book %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} {% include 'snippets/shelve_button/shelve_button.html' with book=book %}
-
- {% endwith %} - {% endif %} + {% endwith %} + {% endif %} -
- {% if status_type == 'Review' %} -
-

- {{ status.name|escape }} -

- -

-

-
- {% endif %} +

+

+ {% endif %} - {% if status.quote %} -
-
{{ status.quote | safe }}
+ {% if status.content_warning %} +
+

{{ status.content_warning }}

-

— {% include 'snippets/book_titleby.html' with book=status.book %}

+ {% trans "Show more" as button_text %} + + {% with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %} + {% include 'snippets/toggle/open_button.html' %} + {% endwith %}
{% endif %} - {% if status.content and status_type != 'GeneratedNote' and status_type != 'Announce' %} - {% with full=status.content|safe no_trim=status.content_warning itemprop=body_prop %} - {% include 'snippets/trimmed_text.html' %} - {% endwith %} - {% endif %} +
+ {% endif %} + + {% if status.content and status_type != 'GeneratedNote' and status_type != 'Announce' %} + {% with full=status.content|safe no_trim=status.content_warning itemprop="reviewBody" %} + {% include 'snippets/trimmed_text.html' %} + {% endwith %} + {% endif %} + + {% if status.attachments.exists %} +
+
+ {% for attachment in status.attachments.all %} +
+
+ + {{ attachment.caption }} + +
+
+ {% endfor %} +
+
+ {% endif %} +
+ +
{% endwith %} diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html index f4186cd10..f3bbae44b 100644 --- a/bookwyrm/templates/snippets/status/generated_status.html +++ b/bookwyrm/templates/snippets/status/generated_status.html @@ -3,29 +3,9 @@ {% load bookwyrm_tags %} {% load i18n %} -{% if status_type == 'Rating' %} -
-
- - - - {# @todo Is it possible to not hard-code the value? #} - - - - {% include 'snippets/stars.html' with rating=status.rating %} -
-
-{% endif %} - {% if not hide_book %} {% with book=status.book|default:status.mention_books.first %} -
+
{% include 'snippets/book_cover.html' with book=book size="small" %} diff --git a/bookwyrm/templates/snippets/status/status_header.html b/bookwyrm/templates/snippets/status/status_header.html index 6493bd548..0fa74ddd1 100644 --- a/bookwyrm/templates/snippets/status/status_header.html +++ b/bookwyrm/templates/snippets/status/status_header.html @@ -40,10 +40,29 @@ {% endwith %} {% endif %} + {% if status.book %} -{{ status.book.title }} + {% if status.status_type == 'GeneratedNote' or status.status_type == 'Rating' %} + {{ status.book.title }}{% if status.status_type == 'Rating' %}: + + + + {% include 'snippets/stars.html' with rating=status.rating %} + {% endif %} + {% else %} + {% include 'snippets/book_titleby.html' with book=status.book %} + {% endif %} {% elif status.mention_books %} -{{ status.mention_books.first.title }} + {{ status.mention_books.first.title }} {% endif %} {% if status.progress %} From cbccb0725213a4a87b3d01e27088469abd5111b2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 11:18:59 -0700 Subject: [PATCH 030/109] Fixes display of replies --- bookwyrm/templates/snippets/status/content_status.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html index 44c52c836..5021ee067 100644 --- a/bookwyrm/templates/snippets/status/content_status.html +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -15,11 +15,13 @@
{% if not hide_book %} {% with book=status.book|default:status.mention_books.first %} + {% if book %}
{% include 'snippets/book_cover.html' with book=book %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} {% include 'snippets/shelve_button/shelve_button.html' with book=book %}
+ {% endif %} {% endwith %} {% endif %} From b22d1863c965db115d35580ceb2f5752cd6d21cb Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 12:31:45 -0700 Subject: [PATCH 031/109] More robust user page test and bug fix --- bookwyrm/tests/views/test_user.py | 8 ++++++++ bookwyrm/views/books.py | 4 ++-- bookwyrm/views/user.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py index 055edae25..7518b2bf0 100644 --- a/bookwyrm/tests/views/test_user.py +++ b/bookwyrm/tests/views/test_user.py @@ -30,6 +30,14 @@ class UserViews(TestCase): self.rat = models.User.objects.create_user( "rat@local.com", "rat@rat.rat", "password", local=True, localname="rat" ) + self.book = models.Edition.objects.create(title="test") + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + models.ShelfBook.objects.create( + book=self.book, + user=self.local_user, + shelf=self.local_user.shelf_set.first(), + ) + models.SiteSettings.objects.create() self.anonymous_user = AnonymousUser self.anonymous_user.is_authenticated = False diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 2a47c0d2b..0c61d1a20 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -270,10 +270,10 @@ class Editions(View): if request.GET.get("format"): filters["physical_format__iexact"] = request.GET.get("format") - editions = work.editions.order_by("-edition_rank").all() + editions = work.editions.order_by("-edition_rank") languages = set(sum([e.languages for e in editions], [])) - paginated = Paginator(editions.filter(**filters).all(), PAGE_LENGTH) + paginated = Paginator(editions.filter(**filters), PAGE_LENGTH) data = { "editions": paginated.get_page(request.GET.get("page")), "work": work, diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index 9c79a77c2..02db5971b 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -59,7 +59,7 @@ class User(View): { "name": user_shelf.name, "local_path": user_shelf.local_path, - "books": user_shelf.books[:3], + "books": user_shelf.books.all()[:3], "size": user_shelf.books.count(), } ) From d47bbde651d8b3d7e7250f67dfb76bbf809e2b1d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 13:02:43 -0700 Subject: [PATCH 032/109] Only one row of footer on list items --- bookwyrm/templates/lists/list.html | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index 2f0e7d678..a9f8e5c0e 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -30,26 +30,32 @@ {% include 'snippets/shelve_button/shelve_button.html' with book=item.book %}
- From 7012f95d6d5623c60b4355869c8774825722a99f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 13:07:55 -0700 Subject: [PATCH 033/109] Use input instead of textarea for series --- bookwyrm/templates/book/edit_book.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/edit_book.html b/bookwyrm/templates/book/edit_book.html index af5d4d695..1702cf5d8 100644 --- a/bookwyrm/templates/book/edit_book.html +++ b/bookwyrm/templates/book/edit_book.html @@ -109,7 +109,10 @@

{{ error | escape }}

{% endfor %} -

{{ form.series }}

+

+ + +

{% for error in form.series.errors %}

{{ error | escape }}

{% endfor %} From c07dcb54580738599833986140c8cea1310504de Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 13:38:25 -0700 Subject: [PATCH 034/109] Remove spaceless templatetags that cause rendering issues in statuses --- bookwyrm/templates/snippets/status/status_content.html | 3 --- bookwyrm/templates/snippets/trimmed_text.html | 2 -- 2 files changed, 5 deletions(-) diff --git a/bookwyrm/templates/snippets/status/status_content.html b/bookwyrm/templates/snippets/status/status_content.html index 402c4aabd..fd3c7ee70 100644 --- a/bookwyrm/templates/snippets/status/status_content.html +++ b/bookwyrm/templates/snippets/status/status_content.html @@ -1,5 +1,3 @@ -{% spaceless %} - {% load bookwyrm_tags %} {% load i18n %} @@ -134,4 +132,3 @@ {% endif %} {% endif %} {% endwith %} -{% endspaceless %} diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index e1728b8f6..6a3fa007b 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -1,4 +1,3 @@ -{% spaceless %} {% load bookwyrm_tags %} {% load i18n %} @@ -46,4 +45,3 @@ {% endwith %} {% endif %} {% endwith %} -{% endspaceless %} From 5fc1e3f2feae807ae84594d6b3e8b193f6fa01e7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 20 Apr 2021 13:50:05 -0700 Subject: [PATCH 035/109] Fixes merge regression for localized timestamps --- bookwyrm/templates/snippets/status/layout.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html index 5b6c0c78d..00e15857e 100644 --- a/bookwyrm/templates/snippets/status/layout.html +++ b/bookwyrm/templates/snippets/status/layout.html @@ -1,6 +1,5 @@ {% extends 'components/card.html' %} {% load i18n %} - {% load bookwyrm_tags %} {% load humanize %} @@ -61,7 +60,7 @@
{% if not moderation_mode %}
{{ user.username }}{{ user.username }} {{ user.created_date }} {{ user.last_active_date }} {% if user.is_active %}{% trans "Active" %}{% else %}{% trans "Inactive" %}{% endif %}
- - - - - - - - - {% if ratings %}{% endif %} - {% if shelf.user == request.user %} - - {% endif %} - - {% for book in books %} - - - - - - {% latest_read_through book user as read_through %} - - - {% if ratings %} - - {% endif %} - {% if shelf.user == request.user %} - - {% endif %} - - {% endfor %} +
{% trans "Cover" %}{% trans "Title" %}{% trans "Author" %}{% trans "Shelved" %}{% trans "Started" %}{% trans "Finished" %}{% trans "Rating" %}
- {% include 'snippets/book_cover.html' with book=book size="small" %} - - {{ book.title }} - - {% include 'snippets/authors.html' %} - - {{ book.created_date | naturalday }} - - {{ read_through.start_date | naturalday |default_if_none:""}} - - {{ read_through.finish_date | naturalday |default_if_none:""}} - - {% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %} - - {% with right=True %} - {% if not shelf.id %} - {% active_shelf book as current %} - {% include 'snippets/shelf_selector.html' with current=current.shelf class="is-small" %} - {% else %} - {% include 'snippets/shelf_selector.html' with current=shelf class="is-small" %} - {% endif %} - {% endwith %} -
+ + + + + + + + + {% if ratings %}{% endif %} + {% if shelf.user == request.user %} + + {% endif %} + + + + {% for book in books %} + {% spaceless %} + + + + + + {% latest_read_through book user as read_through %} + + + {% if ratings %} + + {% endif %} + {% if shelf.user == request.user %} + + {% endif %} + + {% endspaceless %} + {% endfor %} +
{% trans "Cover" %}{% trans "Title" %}{% trans "Author" %}{% trans "Shelved" %}{% trans "Started" %}{% trans "Finished" %}{% trans "Rating" %}
+ {% include 'snippets/book_cover.html' with book=book size="small" %} + + {{ book.title }} + + {% include 'snippets/authors.html' %} + + {{ book.created_date | naturalday }} + + {{ read_through.start_date | naturalday |default_if_none:""}} + + {{ read_through.finish_date | naturalday |default_if_none:""}} + + {% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %} + + {% with right=True %} + {% if not shelf.id %} + {% active_shelf book as current %} + {% include 'snippets/shelf_selector.html' with current=current.shelf class="is-small" %} + {% else %} + {% include 'snippets/shelf_selector.html' with current=shelf class="is-small" %} + {% endif %} + {% endwith %} +
-
{% else %}

{% trans "This shelf is empty." %}

{% if shelf.id and shelf.editable %} From 2ae9085e55e8bdd25c3660560e95b4a97e3d6a3e Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 21:26:20 +0200 Subject: [PATCH 047/109] Vertically align cells in desktop view --- bookwyrm/static/css/bookwyrm.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index a8a29fa2e..5b5b32587 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -260,6 +260,10 @@ body { /* Book preview table ******************************************************************************/ +.book-preview td { + vertical-align: middle; +} + @media only screen and (max-width: 768px) { table.is-mobile, table.is-mobile tbody { display: block; From e4836bd9b3321c79e1496cad1c9e6b6af4ed9791 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 21:29:28 +0200 Subject: [PATCH 048/109] Fix for lint --- bookwyrm/static/css/bookwyrm.css | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 5b5b32587..c019f996c 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -265,15 +265,18 @@ body { } @media only screen and (max-width: 768px) { - table.is-mobile, table.is-mobile tbody { + table.is-mobile, + table.is-mobile tbody { display: block; } + table.is-mobile tr { display: flex; flex-wrap: wrap; justify-content: space-between; border-top: 1px solid #dbdbdb; } + table.is-mobile td { display: block; box-sizing: border-box; @@ -281,20 +284,25 @@ body { order: 2; border-bottom: 0; } + table.is-mobile td.book-preview-top-row { order: 1; flex-basis: auto; } + table.is-mobile td[data-title]:not(:empty)::before { content: attr(data-title); display: block; - font-size: .75em; + font-size: 0.75em; font-weight: bold; } + table.is-mobile td:empty { padding: 0; } - table.is-mobile th, table.is-mobile thead { + + table.is-mobile th, + table.is-mobile thead { display: none; } } From 265c38e877ae907dc64caa26e2c680a51e78a8b1 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 21:31:58 +0200 Subject: [PATCH 049/109] Update direct message button style --- bookwyrm/templates/snippets/status/status_options.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/status/status_options.html b/bookwyrm/templates/snippets/status/status_options.html index 1dbca910d..0749e1c29 100644 --- a/bookwyrm/templates/snippets/status/status_options.html +++ b/bookwyrm/templates/snippets/status/status_options.html @@ -32,7 +32,9 @@ {% else %} {# things you can do to other people's statuses #}
{% endif %} - {% block card-footer %} - {% endblock %} +
+ {% block card-footer %} + {% endblock %} +
{% block card-bonus %} {% endblock %} diff --git a/bookwyrm/templates/moderation/report_preview.html b/bookwyrm/templates/moderation/report_preview.html index 936c04b8f..363783d50 100644 --- a/bookwyrm/templates/moderation/report_preview.html +++ b/bookwyrm/templates/moderation/report_preview.html @@ -16,24 +16,22 @@ {% endblock %} {% block card-footer %} -
- - - -
+ + + {% endblock %} diff --git a/bookwyrm/templates/snippets/goal_card.html b/bookwyrm/templates/snippets/goal_card.html index 5014b81cf..329fea542 100644 --- a/bookwyrm/templates/snippets/goal_card.html +++ b/bookwyrm/templates/snippets/goal_card.html @@ -17,11 +17,9 @@ {% endblock %} {% block card-footer %} -
- -
+ {% endblock %} From 415a12cf787682bbf8b0590ccf14c46415e081f2 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 22:30:52 +0200 Subject: [PATCH 053/109] Move H3 tag --- bookwyrm/templates/snippets/status/layout.html | 6 +++--- bookwyrm/templates/snippets/status/status_header.html | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html index 68feb8971..7ef269af8 100644 --- a/bookwyrm/templates/snippets/status/layout.html +++ b/bookwyrm/templates/snippets/status/layout.html @@ -4,9 +4,9 @@ {% load humanize %} {% block card-header %} -

- {% include 'snippets/status/status_header.html' with status=status %} -

+
+ {% include 'snippets/status/status_header.html' with status=status %} +
{% endblock %} {% block card-content %}{% endblock %} diff --git a/bookwyrm/templates/snippets/status/status_header.html b/bookwyrm/templates/snippets/status/status_header.html index 27bce0ca5..ca8b599c0 100644 --- a/bookwyrm/templates/snippets/status/status_header.html +++ b/bookwyrm/templates/snippets/status/status_header.html @@ -10,7 +10,7 @@
-

+

{{ status.published_date|timesince }} {% if status.progress %} From b1fea9845810db0503afcd36e55fb4a4032eacd3 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 22:31:27 +0200 Subject: [PATCH 054/109] Use one card-footer-item per footer button --- .../templates/snippets/status/layout.html | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html index 7ef269af8..28bfe6213 100644 --- a/bookwyrm/templates/snippets/status/layout.html +++ b/bookwyrm/templates/snippets/status/layout.html @@ -12,8 +12,8 @@ {% block card-content %}{% endblock %} {% block card-footer %} -

- {% if moderation_mode and perms.bookwyrm.moderate_post %} +{% if moderation_mode and perms.bookwyrm.moderate_post %} + +{% elif no_interact %} +{# nothing here #} +{% elif request.user.is_authenticated %} + + + +{% if not moderation_mode %} + +{% endif %} - {% else %} +{% else %} + +{% endif %} {% endblock %} - {% block card-bonus %} {% if request.user.is_authenticated and not moderation_mode %} {% with status.id|uuid as uuid %} From 0b0a283e641db55c231bb1afc5a2bef776de2f2b Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 22:32:14 +0200 Subject: [PATCH 055/109] Fix buttons styles --- bookwyrm/static/css/bookwyrm.css | 24 +++++++++++++++++++ bookwyrm/templates/snippets/boost_button.html | 12 +++++----- bookwyrm/templates/snippets/fav_button.html | 12 +++++----- .../snippets/status/status_options.html | 4 ++-- .../snippets/toggle/toggle_button.html | 6 ++--- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 67eb1ebac..0d790e2a9 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -30,6 +30,30 @@ body { min-width: 75% !important; } +/** Utils + ******************************************************************************/ + +@media only screen and (max-width: 768px) { + .is-sr-only-mobile { + border: none !important; + clip: rect(0,0,0,0) !important; + height: .01em !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + white-space: nowrap !important; + width: .01em !important; + } + + .m-0-mobile { + margin: 0 !important; + } +} + +.button.is-transparent { + background-color: transparent; +} + /** Shelving ******************************************************************************/ diff --git a/bookwyrm/templates/snippets/boost_button.html b/bookwyrm/templates/snippets/boost_button.html index 27a6196a9..3a01fc82d 100644 --- a/bookwyrm/templates/snippets/boost_button.html +++ b/bookwyrm/templates/snippets/boost_button.html @@ -4,16 +4,16 @@ {% with status.id|uuid as uuid %}
{% csrf_token %} -
{% csrf_token %} -
{% endwith %} diff --git a/bookwyrm/templates/snippets/fav_button.html b/bookwyrm/templates/snippets/fav_button.html index da6e6661f..cd22822a5 100644 --- a/bookwyrm/templates/snippets/fav_button.html +++ b/bookwyrm/templates/snippets/fav_button.html @@ -3,17 +3,17 @@ {% with status.id|uuid as uuid %}
{% csrf_token %} -
{% csrf_token %} -
{% endwith %} diff --git a/bookwyrm/templates/snippets/status/status_options.html b/bookwyrm/templates/snippets/status/status_options.html index 16d49b3d2..763d09b8d 100644 --- a/bookwyrm/templates/snippets/status/status_options.html +++ b/bookwyrm/templates/snippets/status/status_options.html @@ -3,8 +3,8 @@ {% load bookwyrm_tags %} {% block dropdown-trigger %} - -{% trans "More options" %} + +{% trans "More options" %} {% endblock %} {% block dropdown-list %} diff --git a/bookwyrm/templates/snippets/toggle/toggle_button.html b/bookwyrm/templates/snippets/toggle/toggle_button.html index d5a8f3dcd..410f823bd 100644 --- a/bookwyrm/templates/snippets/toggle/toggle_button.html +++ b/bookwyrm/templates/snippets/toggle/toggle_button.html @@ -10,12 +10,12 @@ > {% if icon %} - + {{ text }} {% elif icon_with_text %} - - {{ text }} + + {{ text }} {% else %} {{ text }} {% endif %} From 7a5ea31ee757bc13e4cf76a90b44b1a4825c0ce7 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 22:32:26 +0200 Subject: [PATCH 056/109] Fix progress display in title --- .../templates/snippets/status/status_header.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templates/snippets/status/status_header.html b/bookwyrm/templates/snippets/status/status_header.html index ca8b599c0..b833b92c0 100644 --- a/bookwyrm/templates/snippets/status/status_header.html +++ b/bookwyrm/templates/snippets/status/status_header.html @@ -79,14 +79,12 @@

{{ status.published_date|timesince }} {% if status.progress %} - - {% spaceless %} - ({% if status.progress_mode == 'PG' %} - {% include 'snippets/page_text.html' with page=status.progress total_pages=status.book.pages %} + + {% if status.progress_mode == 'PG' %} + ({% include 'snippets/page_text.html' with page=status.progress total_pages=status.book.pages %}) {% else %} - {{ status.progress }}% - {% endif %}) - {% endspaceless %} + ({{ status.progress }}%) + {% endif %} {% endif %} {% include 'snippets/privacy-icons.html' with item=status %} From 2749e6ad9566d059a76bb78505944efcac6d428f Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 22:36:07 +0200 Subject: [PATCH 057/109] Fix CSS for linter --- bookwyrm/static/css/bookwyrm.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 0d790e2a9..74fe76ae5 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -34,15 +34,15 @@ body { ******************************************************************************/ @media only screen and (max-width: 768px) { - .is-sr-only-mobile { + .is-sr-only-mobile { border: none !important; - clip: rect(0,0,0,0) !important; - height: .01em !important; + clip: rect(0, 0, 0, 0) !important; + height: 0.01em !important; overflow: hidden !important; padding: 0 !important; position: absolute !important; white-space: nowrap !important; - width: .01em !important; + width: 0.01em !important; } .m-0-mobile { From 1472f7d919e61df07ad958566cbb42e168cbc0c0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 06:58:21 -0700 Subject: [PATCH 058/109] Restores markdown rendering in book description previews --- bookwyrm/templates/snippets/status/generated_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html index f3bbae44b..cb65a6f29 100644 --- a/bookwyrm/templates/snippets/status/generated_status.html +++ b/bookwyrm/templates/snippets/status/generated_status.html @@ -13,7 +13,7 @@

{% include 'snippets/book_titleby.html' with book=book %}

-

{{ book|book_description|default:""|truncatewords_html:20 }}

+

{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:20 }}

{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
From ae5e7447312727169cde797ecbfc04a1c889e6ad Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 07:29:09 -0700 Subject: [PATCH 059/109] Save last edited by user --- bookwyrm/activitypub/book.py | 1 + bookwyrm/models/activitypub_mixin.py | 6 +++--- bookwyrm/models/book.py | 6 +++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bookwyrm/activitypub/book.py b/bookwyrm/activitypub/book.py index 7615adcf7..538fa571e 100644 --- a/bookwyrm/activitypub/book.py +++ b/bookwyrm/activitypub/book.py @@ -11,6 +11,7 @@ class Book(ActivityObject): """ serializes an edition or work, abstract """ title: str + lastEditedBy: str = None sortTitle: str = "" subtitle: str = "" description: str = "" diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index f687e96cb..71e02082b 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -148,14 +148,14 @@ class ActivitypubMixin: mentions = self.recipients if hasattr(self, "recipients") else [] # we always send activities to explicitly mentioned users' inboxes - recipients = [u.inbox for u in mentions or []] + recipients = [u.inbox for u in mentions or [] if not u.local] # unless it's a dm, all the followers should receive the activity if privacy != "direct": # we will send this out to a subset of all remote users queryset = user_model.viewer_aware_objects(user).filter( local=False, - ) + ).distinct() # filter users first by whether they're using the desired software # this lets us send book updates only to other bw servers if software: @@ -175,7 +175,7 @@ class ActivitypubMixin: "inbox", flat=True ) recipients += list(shared_inboxes) + list(inboxes) - return recipients + return list(set(recipients)) def to_activity_dataclass(self): """ convert from a model to an activity """ diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index a6824c0ad..5280c7aaf 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -26,7 +26,11 @@ class BookDataModel(ObjectMixin, BookWyrmModel): max_length=255, blank=True, null=True, deduplication_field=True ) - last_edited_by = models.ForeignKey("User", on_delete=models.PROTECT, null=True) + last_edited_by = fields.ForeignKey( + "User", + on_delete=models.PROTECT, + null=True, + ) class Meta: """ can't initialize this model, that wouldn't make sense """ From c405580e8e2b28b4738d1140d99e5b8ffbf0b0dd Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 07:37:12 -0700 Subject: [PATCH 060/109] Updates edition federation test --- bookwyrm/tests/data/bw_edition.json | 1 + .../tests/views/inbox/test_inbox_update.py | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/bookwyrm/tests/data/bw_edition.json b/bookwyrm/tests/data/bw_edition.json index 0cc17d29a..6194e4090 100644 --- a/bookwyrm/tests/data/bw_edition.json +++ b/bookwyrm/tests/data/bw_edition.json @@ -1,5 +1,6 @@ { "id": "https://bookwyrm.social/book/5989", + "lastEditedBy": "https://example.com/users/rat", "type": "Edition", "authors": [ "https://bookwyrm.social/author/417" diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py index 012343e78..114eae23d 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_update.py +++ b/bookwyrm/tests/views/inbox/test_inbox_update.py @@ -23,6 +23,16 @@ class InboxUpdate(TestCase): ) self.local_user.remote_id = "https://example.com/user/mouse" self.local_user.save(broadcast=False) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) self.create_json = { "id": "hi", @@ -34,7 +44,7 @@ class InboxUpdate(TestCase): } models.SiteSettings.objects.create() - def test_handle_update_list(self): + def test_update_list(self): """ a new list """ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): book_list = models.List.objects.create( @@ -68,7 +78,7 @@ class InboxUpdate(TestCase): self.assertEqual(book_list.description, "summary text") self.assertEqual(book_list.remote_id, "https://example.com/list/22") - def test_handle_update_user(self): + def test_update_user(self): """ update an existing user """ # we only do this with remote users self.local_user.local = False @@ -94,7 +104,7 @@ class InboxUpdate(TestCase): self.assertEqual(user.localname, "mouse") self.assertTrue(user.discoverable) - def test_handle_update_edition(self): + def test_update_edition(self): """ update an existing edition """ datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_edition.json") bookdata = json.loads(datafile.read_bytes()) @@ -123,7 +133,7 @@ class InboxUpdate(TestCase): book = models.Edition.objects.get(id=book.id) self.assertEqual(book.title, "Piranesi") - def test_handle_update_work(self): + def test_update_work(self): """ update an existing edition """ datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_work.json") bookdata = json.loads(datafile.read_bytes()) From db09ca43312fbbfafcda1d792db130cb358f2548 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 07:51:06 -0700 Subject: [PATCH 061/109] Adds last edited by to author --- bookwyrm/activitypub/book.py | 1 + bookwyrm/models/activitypub_mixin.py | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bookwyrm/activitypub/book.py b/bookwyrm/activitypub/book.py index 538fa571e..c5b896e34 100644 --- a/bookwyrm/activitypub/book.py +++ b/bookwyrm/activitypub/book.py @@ -65,6 +65,7 @@ class Author(ActivityObject): """ author of a book """ name: str + lastEditedBy: str = None born: str = None died: str = None aliases: List[str] = field(default_factory=lambda: []) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 71e02082b..82a45ac86 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -153,9 +153,13 @@ class ActivitypubMixin: # unless it's a dm, all the followers should receive the activity if privacy != "direct": # we will send this out to a subset of all remote users - queryset = user_model.viewer_aware_objects(user).filter( - local=False, - ).distinct() + queryset = ( + user_model.viewer_aware_objects(user) + .filter( + local=False, + ) + .distinct() + ) # filter users first by whether they're using the desired software # this lets us send book updates only to other bw servers if software: From dd0aa7a12394fec47d37c7999f30e6e566d17d19 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 08:08:03 -0700 Subject: [PATCH 062/109] Test that remote user is being set on books --- bookwyrm/tests/views/inbox/test_inbox_update.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py index 114eae23d..fbd377388 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_update.py +++ b/bookwyrm/tests/views/inbox/test_inbox_update.py @@ -132,6 +132,7 @@ class InboxUpdate(TestCase): ) book = models.Edition.objects.get(id=book.id) self.assertEqual(book.title, "Piranesi") + self.assertEqual(book.last_edited_by, self.remote_user) def test_update_work(self): """ update an existing edition """ From d5b27e2202d806f52460e83c28d2d6ea49aa2ac7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 08:31:32 -0700 Subject: [PATCH 063/109] Test re-following a user --- .../tests/views/inbox/test_inbox_follow.py | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_follow.py b/bookwyrm/tests/views/inbox/test_inbox_follow.py index c549c31bd..b0177cb88 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_follow.py +++ b/bookwyrm/tests/views/inbox/test_inbox_follow.py @@ -1,4 +1,5 @@ """ tests incoming activities""" +import json from unittest.mock import patch from django.test import TestCase @@ -34,7 +35,7 @@ class InboxRelationships(TestCase): models.SiteSettings.objects.create() - def test_handle_follow(self): + def test_follow(self): """ remote user wants to follow local user """ activity = { "@context": "https://www.w3.org/ns/activitystreams", @@ -48,6 +49,8 @@ class InboxRelationships(TestCase): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock: views.inbox.activity_task(activity) self.assertEqual(mock.call_count, 1) + response_activity = json.loads(mock.call_args[0][1]) + self.assertEqual(response_activity["type"], "Accept") # notification created notification = models.Notification.objects.get() @@ -61,7 +64,34 @@ class InboxRelationships(TestCase): follow = models.UserFollows.objects.get(user_object=self.local_user) self.assertEqual(follow.user_subject, self.remote_user) - def test_handle_follow_manually_approved(self): + def test_follow_duplicate(self): + """ remote user wants to follow local user twice """ + activity = { + "@context": "https://www.w3.org/ns/activitystreams", + "id": "https://example.com/users/rat/follows/123", + "type": "Follow", + "actor": "https://example.com/users/rat", + "object": "https://example.com/user/mouse", + } + + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + views.inbox.activity_task(activity) + + # the follow relationship should exist + follow = models.UserFollows.objects.get(user_object=self.local_user) + self.assertEqual(follow.user_subject, self.remote_user) + + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock: + views.inbox.activity_task(activity) + self.assertEqual(mock.call_count, 1) + response_activity = json.loads(mock.call_args[0][1]) + self.assertEqual(response_activity["type"], "Accept") + + # the follow relationship should STILL exist + follow = models.UserFollows.objects.get(user_object=self.local_user) + self.assertEqual(follow.user_subject, self.remote_user) + + def test_follow_manually_approved(self): """ needs approval before following """ activity = { "@context": "https://www.w3.org/ns/activitystreams", @@ -91,7 +121,7 @@ class InboxRelationships(TestCase): follow = models.UserFollows.objects.all() self.assertEqual(list(follow), []) - def test_handle_undo_follow_request(self): + def test_undo_follow_request(self): """ the requester cancels a follow request """ self.local_user.manually_approves_followers = True self.local_user.save(broadcast=False) @@ -121,7 +151,7 @@ class InboxRelationships(TestCase): self.assertFalse(self.local_user.follower_requests.exists()) - def test_handle_unfollow(self): + def test_unfollow(self): """ remove a relationship """ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): rel = models.UserFollows.objects.create( @@ -146,7 +176,7 @@ class InboxRelationships(TestCase): views.inbox.activity_task(activity) self.assertIsNone(self.local_user.followers.first()) - def test_handle_follow_accept(self): + def test_follow_accept(self): """ a remote user approved a follow request from local """ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): rel = models.UserFollowRequest.objects.create( @@ -177,7 +207,7 @@ class InboxRelationships(TestCase): self.assertEqual(follows.count(), 1) self.assertEqual(follows.first(), self.local_user) - def test_handle_follow_reject(self): + def test_follow_reject(self): """ turn down a follow request """ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): rel = models.UserFollowRequest.objects.create( From 6b84e53ddde07d68f293393a42158911a90c3686 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 08:40:32 -0700 Subject: [PATCH 064/109] Send accepts to duplicate follow requests --- bookwyrm/models/relationship.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py index 927c87407..3f849597a 100644 --- a/bookwyrm/models/relationship.py +++ b/bookwyrm/models/relationship.py @@ -101,12 +101,15 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship): def save(self, *args, broadcast=True, **kwargs): """ make sure the follow or block relationship doesn't already exist """ - # don't create a request if a follow already exists + # if there's a request for a follow that already exists, accept it + # without changing the local database state if UserFollows.objects.filter( user_subject=self.user_subject, user_object=self.user_object, ).exists(): - raise IntegrityError() + self.accept(broadcast_only=True) + return + # blocking in either direction is a no-go if UserBlocks.objects.filter( Q( @@ -141,9 +144,9 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship): """ get id for sending an accept or reject of a local user """ base_path = self.user_object.remote_id - return "%s#%s/%d" % (base_path, status, self.id) + return "%s#%s/%d" % (base_path, status, self.id or 0) - def accept(self): + def accept(self, broadcast_only=False): """ turn this request into the real deal""" user = self.user_object if not self.user_subject.local: @@ -153,6 +156,9 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship): object=self.to_activity(), ).serialize() self.broadcast(activity, user) + if broadcast_only: + return + with transaction.atomic(): UserFollows.from_request(self) self.delete() From c7daf27baf06b24c9f4104b3114645419c917598 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 09:06:26 -0700 Subject: [PATCH 065/109] Adds migration for last edited by field --- .../migrations/0069_auto_20210422_1604.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 bookwyrm/migrations/0069_auto_20210422_1604.py diff --git a/bookwyrm/migrations/0069_auto_20210422_1604.py b/bookwyrm/migrations/0069_auto_20210422_1604.py new file mode 100644 index 000000000..6591e7b92 --- /dev/null +++ b/bookwyrm/migrations/0069_auto_20210422_1604.py @@ -0,0 +1,34 @@ +# Generated by Django 3.1.8 on 2021-04-22 16:04 + +import bookwyrm.models.fields +from django.conf import settings +from django.db import migrations +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0068_ordering_for_list_items"), + ] + + operations = [ + migrations.AlterField( + model_name="author", + name="last_edited_by", + field=bookwyrm.models.fields.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="book", + name="last_edited_by", + field=bookwyrm.models.fields.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ] From e9dc63e296a926e9e510b780eb9742127898ca33 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 09:25:12 -0700 Subject: [PATCH 066/109] Only remove objects that are known --- bookwyrm/activitypub/verbs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/activitypub/verbs.py b/bookwyrm/activitypub/verbs.py index c2cbfea31..090beea5f 100644 --- a/bookwyrm/activitypub/verbs.py +++ b/bookwyrm/activitypub/verbs.py @@ -176,7 +176,8 @@ class Remove(Add): def action(self): """ find and remove the activity object """ obj = self.object.to_model(save=False, allow_create=False) - obj.delete() + if obj: + obj.delete() @dataclass(init=False) From cfa424ca59d0d52c832ad4b0011bfda1df07741a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 09:37:24 -0700 Subject: [PATCH 067/109] Fixes nondeterministic test outcome --- bookwyrm/tests/models/test_activitypub_mixin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py index 0d1acd978..e172ede96 100644 --- a/bookwyrm/tests/models/test_activitypub_mixin.py +++ b/bookwyrm/tests/models/test_activitypub_mixin.py @@ -155,8 +155,8 @@ class ActivitypubMixins(TestCase): recipients = ActivitypubMixin.get_recipients(mock_self) self.assertEqual(len(recipients), 2) - self.assertEqual(recipients[0], another_remote_user.inbox) - self.assertEqual(recipients[1], self.remote_user.inbox) + self.assertTrue(another_remote_user.inbox in recipients) + self.assertTrue(self.remote_user.inbox in recipients) def test_get_recipients_direct(self, _): """ determines the recipients for a user's object broadcast """ From a797b68558a9a8245a17a22ac54dba93ad6bd470 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 10:22:37 -0700 Subject: [PATCH 068/109] Adds test that replicates follower deletion bug --- .../tests/views/inbox/test_inbox_update.py | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py index fbd377388..5681ec882 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_update.py +++ b/bookwyrm/tests/views/inbox/test_inbox_update.py @@ -80,14 +80,22 @@ class InboxUpdate(TestCase): def test_update_user(self): """ update an existing user """ - # we only do this with remote users - self.local_user.local = False - self.local_user.save() + models.UserFollows.objects.create( + user_subject=self.local_user, + user_object=self.remote_user, + ) + models.UserFollows.objects.create( + user_subject=self.remote_user, + user_object=self.local_user, + ) + self.assertTrue(self.remote_user in self.local_user.followers.all()) + self.assertTrue(self.local_user in self.remote_user.followers.all()) - datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_user.json") + datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_user_rat.json") userdata = json.loads(datafile.read_bytes()) del userdata["icon"] - self.assertIsNone(self.local_user.name) + self.assertIsNone(self.remote_user.name) + self.assertFalse(self.remote_user.discoverable) views.inbox.activity_task( { "type": "Update", @@ -98,12 +106,15 @@ class InboxUpdate(TestCase): "object": userdata, } ) - user = models.User.objects.get(id=self.local_user.id) - self.assertEqual(user.name, "MOUSE?? MOUSE!!") - self.assertEqual(user.username, "mouse@example.com") - self.assertEqual(user.localname, "mouse") + user = models.User.objects.get(id=self.remote_user.id) + self.assertEqual(user.name, "RAT???") + self.assertEqual(user.username, "rat@example.com") self.assertTrue(user.discoverable) + # make sure relationships aren't disrupted + self.assertTrue(self.remote_user in self.local_user.followers.all()) + self.assertTrue(self.local_user in self.remote_user.followers.all()) + def test_update_edition(self): """ update an existing edition """ datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_edition.json") From 3ed822b9ea4339d8ab096bf6bad02d753d09878a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 10:28:10 -0700 Subject: [PATCH 069/109] Don't erase follows on update --- bookwyrm/models/fields.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 2aefae51f..336ee4a1c 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -275,9 +275,12 @@ class ManyToManyField(ActivitypubFieldMixin, models.ManyToManyField): return [i.remote_id for i in value.all()] def field_from_activity(self, value): - items = [] if value is None or value is MISSING: - return [] + return None + if not isinstance(value, list): + # TODO + return None + items = [] for remote_id in value: try: validate_remote_id(remote_id) From c4555852625e505fc14a817e403abb42a2e750c4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 10:30:00 -0700 Subject: [PATCH 070/109] Adds missing data file --- bookwyrm/models/fields.py | 2 +- bookwyrm/tests/data/ap_user_rat.json | 39 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/tests/data/ap_user_rat.json diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 336ee4a1c..a1b2035b1 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -278,7 +278,7 @@ class ManyToManyField(ActivitypubFieldMixin, models.ManyToManyField): if value is None or value is MISSING: return None if not isinstance(value, list): - # TODO + # If this is a link, we currently aren't doing anything with it return None items = [] for remote_id in value: diff --git a/bookwyrm/tests/data/ap_user_rat.json b/bookwyrm/tests/data/ap_user_rat.json new file mode 100644 index 000000000..0e36f1c62 --- /dev/null +++ b/bookwyrm/tests/data/ap_user_rat.json @@ -0,0 +1,39 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "schema": "http://schema.org#", + "PropertyValue": "schema:PropertyValue", + "value": "schema:value" + } + ], + "id": "https://example.com/users/rat", + "type": "Person", + "preferredUsername": "rat", + "name": "RAT???", + "inbox": "https://example.com/users/rat/inbox", + "outbox": "https://example.com/users/rat/outbox", + "followers": "https://example.com/users/rat/followers", + "following": "https://example.com/users/rat/following", + "summary": "", + "publicKey": { + "id": "https://example.com/users/rat/#main-key", + "owner": "https://example.com/users/rat", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6QisDrjOQvkRo/MqNmSYPwqtt\nCxg/8rCW+9jKbFUKvqjTeKVotEE85122v/DCvobCCdfQuYIFdVMk+dB1xJ0iPGPg\nyU79QHY22NdV9mFKA2qtXVVxb5cxpA4PlwOHM6PM/k8B+H09OUrop2aPUAYwy+vg\n+MXyz8bAXrIS1kq6fQIDAQAB\n-----END PUBLIC KEY-----" + }, + "endpoints": { + "sharedInbox": "https://example.com/inbox" + }, + "bookwyrmUser": true, + "manuallyApprovesFollowers": false, + "discoverable": true, + "devices": "https://friend.camp/users/tripofmice/collections/devices", + "tag": [], + "icon": { + "type": "Image", + "mediaType": "image/png", + "url": "https://example.com/images/avatars/AL-2-crop-50.png" + } +} From 00e6d0524f527d09ffa3d1c040111968b0861171 Mon Sep 17 00:00:00 2001 From: Joachim Date: Thu, 22 Apr 2021 20:41:58 +0200 Subject: [PATCH 071/109] Accessibility: add language to `lang` attr on `html` tag I only use the first subtag of the language string given by `get_language()`, because `get_language()` returns an all-lowercase string, and I don't know if it'll be considered valid by browsers. --- bookwyrm/templates/layout.html | 2 +- bookwyrm/templatetags/bookwyrm_tags.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index 4ce7a7f8c..84482cdfc 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -1,7 +1,7 @@ {% load bookwyrm_tags %} {% load i18n %} - + {% block title %}BookWyrm{% endblock %} | {{ site.name }} diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 69e762cef..f1bd025d3 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -1,7 +1,7 @@ """ template filters """ from uuid import uuid4 -from django import template +from django import template, utils from django.db.models import Avg from bookwyrm import models, views @@ -217,3 +217,10 @@ def active_read_through(book, user): def comparison_bool(str1, str2): """ idk why I need to write a tag for this, it reutrns a bool """ return str1 == str2 + + +@register.simple_tag(takes_context=False) +def get_lang(): + """ get current language, strip to the first two letters """ + language = utils.translation.get_language() + return language[0:language.find('-')] From ebf20de10e9dfab157d7924e6a249539dccc3830 Mon Sep 17 00:00:00 2001 From: Joachim Date: Thu, 22 Apr 2021 20:45:16 +0200 Subject: [PATCH 072/109] linter linter go away --- bookwyrm/templatetags/bookwyrm_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index f1bd025d3..30bb1d3fa 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -223,4 +223,4 @@ def comparison_bool(str1, str2): def get_lang(): """ get current language, strip to the first two letters """ language = utils.translation.get_language() - return language[0:language.find('-')] + return language[0 : language.find('-')] From 15241e38074ff7f6f66c55abbadcabd801ad80a7 Mon Sep 17 00:00:00 2001 From: Joachim Date: Thu, 22 Apr 2021 20:48:06 +0200 Subject: [PATCH 073/109] =?UTF-8?q?=E2=80=A6=E2=80=A6=E2=80=A6=20come=20ba?= =?UTF-8?q?ck=20another=20day?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bookwyrm/templatetags/bookwyrm_tags.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 30bb1d3fa..08713bee8 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -223,4 +223,5 @@ def comparison_bool(str1, str2): def get_lang(): """ get current language, strip to the first two letters """ language = utils.translation.get_language() - return language[0 : language.find('-')] + return language[0 : language.find("-")] + From 6c89eb1b650a0c1c8a9c70ddccf08f898d0ad2d6 Mon Sep 17 00:00:00 2001 From: Joachim Date: Thu, 22 Apr 2021 20:48:25 +0200 Subject: [PATCH 074/109] Update bookwyrm_tags.py --- bookwyrm/templatetags/bookwyrm_tags.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 08713bee8..649a0dfa1 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -224,4 +224,3 @@ def get_lang(): """ get current language, strip to the first two letters """ language = utils.translation.get_language() return language[0 : language.find("-")] - From 15c7a1dc8225c3140231a6a1d602df6a785b6f62 Mon Sep 17 00:00:00 2001 From: Joachim Date: Thu, 22 Apr 2021 20:57:24 +0200 Subject: [PATCH 075/109] Update bookwyrm.css --- bookwyrm/static/css/bookwyrm.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 74fe76ae5..fe7617bcc 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -30,7 +30,7 @@ body { min-width: 75% !important; } -/** Utils +/** Utilities not covered by Bulma ******************************************************************************/ @media only screen and (max-width: 768px) { From c6e8161a9f73205a095459542dbd5650babd2077 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 13:08:22 -0700 Subject: [PATCH 076/109] Removes scroll padding --- bookwyrm/static/css/bookwyrm.css | 1 - 1 file changed, 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 67eb1ebac..b4abd6907 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -1,6 +1,5 @@ html { scroll-behavior: smooth; - scroll-padding-top: 20%; } body { From 6915b195cef1d34d0e68e25a621850610382d36c Mon Sep 17 00:00:00 2001 From: reese Date: Tue, 20 Apr 2021 18:22:24 -0500 Subject: [PATCH 077/109] translated some strings --- bookwyrm/templates/moderation/report.html | 2 +- locale/es/LC_MESSAGES/django.po | 166 +++++++++++----------- 2 files changed, 81 insertions(+), 87 deletions(-) diff --git a/bookwyrm/templates/moderation/report.html b/bookwyrm/templates/moderation/report.html index a078fe450..934799e33 100644 --- a/bookwyrm/templates/moderation/report.html +++ b/bookwyrm/templates/moderation/report.html @@ -51,7 +51,7 @@ {% for status in report.statuses.select_subclasses.all %}
  • {% if status.deleted %} - {% trans "Statuses has been deleted" %} + {% trans "Status has been deleted" %} {% else %} {% include 'snippets/status/status.html' with status=status moderation_mode=True %} {% endif %} diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 159e806ab..ecc37932f 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -298,12 +298,12 @@ msgstr "lo calificó con" #, fuzzy #| msgid "Add cover" msgid "Upload cover:" -msgstr "Agregar portada" +msgstr "Agregar portada:" #: bookwyrm/templates/book/cover_modal.html:23 #: bookwyrm/templates/book/edit_book.html:181 msgid "Load cover from url:" -msgstr "" +msgstr "Agregar portada de url:" #: bookwyrm/templates/book/edit_book.html:5 #: bookwyrm/templates/book/edit_book.html:11 @@ -336,12 +336,12 @@ msgstr "Editado más recientemente por:" #: bookwyrm/templates/book/edit_book.html:40 msgid "Confirm Book Info" -msgstr "" +msgstr "Confirmar información de libro" #: bookwyrm/templates/book/edit_book.html:47 #, python-format msgid "Is \"%(name)s\" an existing author?" -msgstr "" +msgstr "¿Es \"%(name)s\" un autor ya existente?" #: bookwyrm/templates/book/edit_book.html:52 #, fuzzy, python-format @@ -351,20 +351,20 @@ msgstr "Empezar \"%(book_title)s\"" #: bookwyrm/templates/book/edit_book.html:55 msgid "This is a new author" -msgstr "" +msgstr "Este es un autor nuevo" #: bookwyrm/templates/book/edit_book.html:61 #, python-format msgid "Creating a new author: %(name)s" -msgstr "" +msgstr "Creando un autor nuevo: %(name)s" #: bookwyrm/templates/book/edit_book.html:67 msgid "Is this an edition of an existing work?" -msgstr "" +msgstr "¿Es esta una edición de una obra ya existente?" #: bookwyrm/templates/book/edit_book.html:71 msgid "This is a new work" -msgstr "" +msgstr "Esta es una obra nueva" #: bookwyrm/templates/book/edit_book.html:77 #: bookwyrm/templates/password_reset.html:30 @@ -405,7 +405,7 @@ msgstr "Publicado" #: bookwyrm/templates/book/edit_book.html:125 msgid "Separate multiple publishers with commas." -msgstr "" +msgstr "Separar varios editores con comas." #: bookwyrm/templates/book/edit_book.html:132 msgid "First published date:" @@ -435,7 +435,7 @@ msgstr "Editar Autor/Autora" #: bookwyrm/templates/book/edit_book.html:161 msgid "John Doe, Jane Smith" -msgstr "" +msgstr "Juan Nadie, Natalia Natalia" #: bookwyrm/templates/book/edit_book.html:167 #: bookwyrm/templates/user/shelf.html:75 @@ -485,11 +485,11 @@ msgstr "Ediciones de \"%(work_title)s\"" #: bookwyrm/templates/book/format_filter.html:8 #: bookwyrm/templates/book/language_filter.html:8 msgid "Any" -msgstr "" +msgstr "Cualquier" #: bookwyrm/templates/book/language_filter.html:5 msgid "Language:" -msgstr "" +msgstr "Idioma:" #: bookwyrm/templates/book/publisher_info.html:6 #, python-format @@ -510,7 +510,7 @@ msgstr "%(pages)s páginas" #: bookwyrm/templates/book/publisher_info.html:18 #, python-format msgid "Published %(date)s by %(publisher)s." -msgstr "" +msgstr "Publicado %(date)s por %(publisher)s." #: bookwyrm/templates/book/publisher_info.html:20 #, fuzzy, python-format @@ -521,7 +521,7 @@ msgstr "Fecha de publicación:" #: bookwyrm/templates/book/publisher_info.html:22 #, python-format msgid "Published by %(publisher)s." -msgstr "" +msgstr "Publicado por %(publisher)s." #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 @@ -559,11 +559,11 @@ msgstr "Federalizado" #: bookwyrm/templates/directory/directory.html:11 #: bookwyrm/templates/layout.html:92 msgid "Directory" -msgstr "" +msgstr "Directorio" #: bookwyrm/templates/directory/directory.html:19 msgid "Make your profile discoverable to other BookWyrm users." -msgstr "" +msgstr "Haz que tu perfil sea reconocible a otros usarios de BookWyrm." #: bookwyrm/templates/directory/directory.html:26 #, fuzzy, python-format @@ -594,15 +594,15 @@ msgstr[1] "Tus estantes" #: bookwyrm/templates/directory/directory.html:86 msgid "posts" -msgstr "" +msgstr "publicaciones" #: bookwyrm/templates/directory/directory.html:92 msgid "last active" -msgstr "" +msgstr "actividad reciente" #: bookwyrm/templates/directory/sort_filter.html:5 msgid "Order by" -msgstr "" +msgstr "Ordenar por" #: bookwyrm/templates/directory/sort_filter.html:8 #, fuzzy @@ -612,7 +612,7 @@ msgstr "Sugerir" #: bookwyrm/templates/directory/sort_filter.html:9 msgid "Recently active" -msgstr "" +msgstr "Activ@ recientemente" #: bookwyrm/templates/directory/user_type_filter.html:5 #, fuzzy @@ -622,11 +622,11 @@ msgstr "Actividad de usuario" #: bookwyrm/templates/directory/user_type_filter.html:8 msgid "BookWyrm users" -msgstr "" +msgstr "Usuarios de BookWyrm" #: bookwyrm/templates/directory/user_type_filter.html:12 msgid "All known users" -msgstr "" +msgstr "Todos los usuarios conocidos" #: bookwyrm/templates/discover/about.html:7 #, python-format @@ -676,11 +676,11 @@ msgstr "Esta instancia está cerrada." #: bookwyrm/templates/discover/landing_layout.html:57 msgid "Thank you! Your request has been received." -msgstr "" +msgstr "¡Gracias! Tu solicitación ha sido recibido." #: bookwyrm/templates/discover/landing_layout.html:60 msgid "Request an Invitation" -msgstr "" +msgstr "Solicitar una invitación" #: bookwyrm/templates/discover/landing_layout.html:64 #: bookwyrm/templates/password_reset_request.html:18 @@ -692,7 +692,7 @@ msgstr "Dirección de correo electrónico:" #: bookwyrm/templates/discover/landing_layout.html:70 #: bookwyrm/templates/moderation/report_modal.html:31 msgid "Submit" -msgstr "" +msgstr "Enviar" #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" @@ -741,16 +741,16 @@ msgstr "Clave Goodreads:" #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," -msgstr "" +msgstr "Hola, " #: bookwyrm/templates/email/html_layout.html:21 #, python-format msgid "BookWyrm hosted on %(site_name)s" -msgstr "" +msgstr "BookWyrm alojado en %(site_name)s" #: bookwyrm/templates/email/html_layout.html:23 msgid "Email preference" -msgstr "" +msgstr "Preferencia de correo electrónico" #: bookwyrm/templates/email/invite/html_content.html:6 #: bookwyrm/templates/email/invite/subject.html:2 @@ -761,17 +761,17 @@ msgstr "Sobre %(site_name)s" #: bookwyrm/templates/email/invite/html_content.html:9 msgid "Join Now" -msgstr "" +msgstr "Únete ahora" #: bookwyrm/templates/email/invite/html_content.html:15 #, python-format msgid "Learn more about this instance." -msgstr "" +msgstr "Aprenda más sobre esta instancia." #: bookwyrm/templates/email/invite/text_content.html:4 #, python-format msgid "You're invited to join %(site_name)s! Click the link below to create an account." -msgstr "" +msgstr "Estás invitado a unirte con %(site_name)s! Haz clic en el enlace debajo para crear una cuenta." #: bookwyrm/templates/email/invite/text_content.html:8 #, fuzzy @@ -783,7 +783,7 @@ msgstr "Más sobre este sitio" #: bookwyrm/templates/email/password_reset/text_content.html:4 #, python-format msgid "You requested to reset your %(site_name)s password. Click the link below to set a new password and log in to your account." -msgstr "" +msgstr "Tú solicitaste reestablecer tu %(site_name)s contraseña. Haz clic en el enlace debajo para establecer una nueva contraseña e ingresar a tu cuenta." #: bookwyrm/templates/email/password_reset/html_content.html:9 #: bookwyrm/templates/password_reset.html:4 @@ -796,7 +796,7 @@ msgstr "Restablecer contraseña" #: bookwyrm/templates/email/password_reset/html_content.html:13 #: bookwyrm/templates/email/password_reset/text_content.html:8 msgid "If you didn't request to reset your password, you can ignore this email." -msgstr "" +msgstr "Si no solicitaste reestablecer tu contraseña, puedes ignorar este mensaje." #: bookwyrm/templates/email/password_reset/subject.html:2 #, fuzzy, python-format @@ -824,19 +824,15 @@ msgstr "No tienes ningún mensaje en este momento." #: bookwyrm/templates/feed/feed.html:9 msgid "Home Timeline" -msgstr "" +msgstr "Línea temporal de hogar" #: bookwyrm/templates/feed/feed.html:11 -#, fuzzy -#| msgid "%(tab_title)s Timeline" msgid "Local Timeline" -msgstr "%(tab_title)s Línea temporal" +msgstr "Línea temporal local" #: bookwyrm/templates/feed/feed.html:13 -#, fuzzy -#| msgid "Federated Servers" msgid "Federated Timeline" -msgstr "Servidores federalizados" +msgstr "Línea temporal federalizado" #: bookwyrm/templates/feed/feed.html:19 msgid "Home" @@ -853,16 +849,16 @@ msgstr "Federalizado" #: bookwyrm/templates/feed/feed.html:33 #, python-format msgid "load 0 unread status(es)" -msgstr "" +msgstr "cargar 0 status(es) no leídos" #: bookwyrm/templates/feed/feed.html:48 msgid "There aren't any activities right now! Try following a user to get started" -msgstr "¡No hay actividades en este momento! Sigue a otro usuario para empezar" +msgstr "¡No hay actividad ahora mismo! Sigue a otro usuario para empezar" #: bookwyrm/templates/feed/feed.html:56 #: bookwyrm/templates/get_started/users.html:6 msgid "Who to follow" -msgstr "" +msgstr "A quién seguir" #: bookwyrm/templates/feed/feed_layout.html:5 msgid "Updates" @@ -941,7 +937,7 @@ msgstr "No se encontró ningún libro correspondiente a \"%(query)s\"" #: bookwyrm/templates/get_started/books.html:11 #, python-format msgid "You can add books when you start using %(site_name)s." -msgstr "" +msgstr "Puedes agregar libros cuando comiences a usar %(site_name)s." #: bookwyrm/templates/get_started/books.html:16 #: bookwyrm/templates/get_started/books.html:17 @@ -972,7 +968,7 @@ msgstr "No se encontró ningún libro" #: bookwyrm/templates/get_started/books.html:54 #: bookwyrm/templates/get_started/profile.html:54 msgid "Save & continue" -msgstr "" +msgstr "Guardar & continuar" #: bookwyrm/templates/get_started/layout.html:14 #, fuzzy, python-format @@ -982,7 +978,7 @@ msgstr "Sobre %(site_name)s" #: bookwyrm/templates/get_started/layout.html:16 msgid "These are some first steps to get you started." -msgstr "" +msgstr "Estos son unos primeros pasos para empezar." #: bookwyrm/templates/get_started/layout.html:30 #: bookwyrm/templates/get_started/profile.html:6 @@ -1005,7 +1001,7 @@ msgstr "Amigable" #: bookwyrm/templates/get_started/layout.html:44 msgid "Skip this step" -msgstr "" +msgstr "Saltar este paso" #: bookwyrm/templates/get_started/layout.html:48 #, fuzzy @@ -1025,7 +1021,7 @@ msgstr "Resumen:" #: bookwyrm/templates/get_started/profile.html:23 msgid "A little bit about you" -msgstr "" +msgstr "Un poco sobre ti" #: bookwyrm/templates/get_started/profile.html:32 #: bookwyrm/templates/preferences/edit_user.html:17 @@ -1040,11 +1036,11 @@ msgstr "Aprobar seguidores a mano:" #: bookwyrm/templates/get_started/profile.html:48 #: bookwyrm/templates/preferences/edit_user.html:58 msgid "Show this account in suggested users:" -msgstr "" +msgstr "Mostrar esta cuenta en los usuarios sugeridos:" #: bookwyrm/templates/get_started/profile.html:52 msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." -msgstr "" +msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm." #: bookwyrm/templates/get_started/users.html:11 #, fuzzy @@ -1101,7 +1097,7 @@ msgstr "Fuente de datos" #: bookwyrm/templates/import.html:29 msgid "Data file:" -msgstr "" +msgstr "Archivo de datos:" #: bookwyrm/templates/import.html:37 msgid "Include reviews" @@ -1155,7 +1151,7 @@ msgstr "Se falló a cargar" #: bookwyrm/templates/import_status.html:44 #, python-format msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import." -msgstr "" +msgstr "Saltar al final de la lista para seleccionar los %(failed_count)s artículos que no se pudieron importar." #: bookwyrm/templates/import_status.html:79 msgid "Select all" @@ -1244,7 +1240,7 @@ msgstr "Invitaciones" #: bookwyrm/templates/layout.html:118 msgid "Admin" -msgstr "" +msgstr "Admin" #: bookwyrm/templates/layout.html:125 msgid "Log out" @@ -1277,7 +1273,7 @@ msgstr "Iniciar sesión" #: bookwyrm/templates/layout.html:168 msgid "Join" -msgstr "" +msgstr "Unirse" #: bookwyrm/templates/layout.html:191 msgid "About this server" @@ -1290,7 +1286,7 @@ msgstr "Contactarse con administradores del sitio" #: bookwyrm/templates/layout.html:202 #, python-format msgid "Support %(site_name)s on %(support_title)s" -msgstr "" +msgstr "Apoyar %(site_name)s en %(support_title)s" #: bookwyrm/templates/layout.html:206 msgid "BookWyrm is open source software. You can contribute or report issues on GitHub." @@ -1461,11 +1457,11 @@ msgstr "Más sobre este sitio" #: bookwyrm/templates/moderation/report_preview.html:6 #, python-format msgid "Report #%(report_id)s: %(username)s" -msgstr "" +msgstr "Reportar #%(report_id)s: %(username)s" #: bookwyrm/templates/moderation/report.html:10 msgid "Back to reports" -msgstr "" +msgstr "Volver a los informes" #: bookwyrm/templates/moderation/report.html:18 #, fuzzy @@ -1487,15 +1483,15 @@ msgstr "Enviar mensaje directo" #: bookwyrm/templates/moderation/report.html:27 msgid "Deactivate user" -msgstr "" +msgstr "Desactivar usuario" #: bookwyrm/templates/moderation/report.html:29 msgid "Reactivate user" -msgstr "" +msgstr "Reactivar usuario" #: bookwyrm/templates/moderation/report.html:36 msgid "Moderator Comments" -msgstr "" +msgstr "Comentarios de moderador" #: bookwyrm/templates/moderation/report.html:54 #: bookwyrm/templates/snippets/create_status.html:28 @@ -1511,11 +1507,11 @@ msgstr "Eliminar status" #: bookwyrm/templates/moderation/report.html:61 msgid "No statuses reported" -msgstr "" +msgstr "Ningún estatus reportado" #: bookwyrm/templates/moderation/report.html:67 -msgid "Statuses has been deleted" -msgstr "" +msgid "Status has been deleted" +msgstr "Status ha sido eliminado" #: bookwyrm/templates/moderation/report_modal.html:6 #, fuzzy, python-format @@ -1526,7 +1522,7 @@ msgstr "Listas: %(username)s" #: bookwyrm/templates/moderation/report_modal.html:21 #, python-format msgid "This report will be sent to %(site_name)s's moderators for review." -msgstr "" +msgstr "Este informe se enviará a los moderadores de %(site_name)s para la revisión." #: bookwyrm/templates/moderation/report_modal.html:22 #, fuzzy @@ -1536,7 +1532,7 @@ msgstr "Más sobre este sitio" #: bookwyrm/templates/moderation/report_preview.html:13 msgid "No notes provided" -msgstr "" +msgstr "No se proporcionó notas" #: bookwyrm/templates/moderation/report_preview.html:20 #, fuzzy, python-format @@ -1546,11 +1542,11 @@ msgstr "Agregado por %(username)s" #: bookwyrm/templates/moderation/report_preview.html:30 msgid "Re-open" -msgstr "" +msgstr "Reabrir" #: bookwyrm/templates/moderation/report_preview.html:32 msgid "Resolve" -msgstr "" +msgstr "Resolver" #: bookwyrm/templates/moderation/reports.html:6 #, fuzzy, python-format @@ -1694,7 +1690,7 @@ msgstr "Tu importación ha terminado." #: bookwyrm/templates/notifications.html:113 #, python-format msgid "A new report needs moderation." -msgstr "" +msgstr "Un informe nuevo se requiere moderación." #: bookwyrm/templates/notifications.html:139 msgid "You're all caught up!" @@ -1741,12 +1737,12 @@ msgstr "Editar perfil" #: bookwyrm/templates/preferences/edit_user.html:46 msgid "Show set reading goal prompt in feed:" -msgstr "" +msgstr "Mostrar meta de lectura en el feed:" #: bookwyrm/templates/preferences/edit_user.html:62 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." -msgstr "" +msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm."" #: bookwyrm/templates/preferences/edit_user.html:65 msgid "Preferred Timezone: " @@ -1797,7 +1793,7 @@ msgstr "Administrar usuarios" #: bookwyrm/templates/settings/user_admin.html:3 #: bookwyrm/templates/settings/user_admin.html:10 msgid "Users" -msgstr "" +msgstr "Usuarios" #: bookwyrm/templates/settings/admin_layout.html:32 #: bookwyrm/templates/settings/federation.html:3 @@ -1837,11 +1833,11 @@ msgstr "Registración" #: bookwyrm/templates/settings/federated_server.html:7 msgid "Back to server list" -msgstr "" +msgstr "Volver a la lista de servidores" #: bookwyrm/templates/settings/federated_server.html:12 msgid "Details" -msgstr "" +msgstr "Detalles" #: bookwyrm/templates/settings/federated_server.html:15 #, fuzzy @@ -1875,7 +1871,7 @@ msgstr "Nombre de usuario:" #: bookwyrm/templates/settings/federated_server.html:36 #: bookwyrm/templates/settings/federated_server.html:43 msgid "View all" -msgstr "" +msgstr "Ver todos" #: bookwyrm/templates/settings/federated_server.html:40 #, fuzzy @@ -1933,7 +1929,7 @@ msgstr "Invitaciones" #: bookwyrm/templates/settings/manage_invite_requests.html:23 msgid "Ignored Invite Requests" -msgstr "" +msgstr "Solicitaciones de invitación ignoradas" #: bookwyrm/templates/settings/manage_invite_requests.html:35 #, fuzzy @@ -1949,7 +1945,7 @@ msgstr "Aceptar" #: bookwyrm/templates/settings/manage_invite_requests.html:42 msgid "Email" -msgstr "" +msgstr "Correo electronico" #: bookwyrm/templates/settings/manage_invite_requests.html:47 #, fuzzy @@ -1965,40 +1961,38 @@ msgstr "Solicitudes de seguidor" #: bookwyrm/templates/settings/manage_invite_requests.html:59 #: bookwyrm/templates/settings/status_filter.html:16 -#, fuzzy -#| msgid "Accept" msgid "Accepted" -msgstr "Aceptar" +msgstr "Aceptado" #: bookwyrm/templates/settings/manage_invite_requests.html:61 #: bookwyrm/templates/settings/status_filter.html:12 msgid "Sent" -msgstr "" +msgstr "Enviado" #: bookwyrm/templates/settings/manage_invite_requests.html:63 #: bookwyrm/templates/settings/status_filter.html:8 msgid "Requested" -msgstr "" +msgstr "Solicitado" #: bookwyrm/templates/settings/manage_invite_requests.html:73 msgid "Send invite" -msgstr "" +msgstr "Enviar invitación" #: bookwyrm/templates/settings/manage_invite_requests.html:75 msgid "Re-send invite" -msgstr "" +msgstr "Re-enviar invitación" #: bookwyrm/templates/settings/manage_invite_requests.html:95 msgid "Ignore" -msgstr "" +msgstr "Ignorar" #: bookwyrm/templates/settings/manage_invite_requests.html:97 msgid "Un-ignore" -msgstr "" +msgstr "Des-ignorar" #: bookwyrm/templates/settings/manage_invite_requests.html:108 msgid "Back to pending requests" -msgstr "" +msgstr "Volver a las solicitaciones pendientes" #: bookwyrm/templates/settings/manage_invite_requests.html:110 msgid "View ignored requests" From d526fdc92f34ed66713b34348ad1307b1912089e Mon Sep 17 00:00:00 2001 From: reese Date: Tue, 20 Apr 2021 18:39:55 -0500 Subject: [PATCH 078/109] more translations --- locale/es/LC_MESSAGES/django.po | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index ecc37932f..acefc2563 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -1996,7 +1996,7 @@ msgstr "Volver a las solicitaciones pendientes" #: bookwyrm/templates/settings/manage_invite_requests.html:110 msgid "View ignored requests" -msgstr "" +msgstr "Ver solicitaciones ignoradas" #: bookwyrm/templates/settings/manage_invites.html:21 msgid "Generate New Invite" @@ -2095,7 +2095,7 @@ msgstr "Texto de registración cerrada:" #: bookwyrm/templates/settings/user_admin.html:7 #, python-format msgid "Users: %(server_name)s" -msgstr "" +msgstr "Usuarios %(server_name)s" #: bookwyrm/templates/settings/user_admin.html:20 #, fuzzy @@ -2111,7 +2111,7 @@ msgstr "Agregado:" #: bookwyrm/templates/settings/user_admin.html:28 msgid "Last Active" -msgstr "" +msgstr "Actividad reciente" #: bookwyrm/templates/settings/user_admin.html:36 #, fuzzy @@ -2127,11 +2127,11 @@ msgstr "Actividad" #: bookwyrm/templates/settings/user_admin.html:45 msgid "Inactive" -msgstr "" +msgstr "Inactiv@" #: bookwyrm/templates/settings/user_admin.html:50 msgid "Not set" -msgstr "" +msgstr "No establecido" #: bookwyrm/templates/snippets/block_button.html:5 msgid "Block" @@ -2265,11 +2265,11 @@ msgstr "Mostrar menos" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:9 msgid "Hide filters" -msgstr "" +msgstr "Ocultar filtros" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:22 msgid "Apply filters" -msgstr "" +msgstr "Aplicar filtros" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:26 #, fuzzy @@ -2333,7 +2333,7 @@ msgstr[1] "" #: bookwyrm/templates/snippets/generated_status/review_pure_name.html:8 #, python-format msgid "Review of \"%(book_title)s\": %(review_title)s" -msgstr "" +msgstr "Reseña de \"%(book_title)s\": %(review_title)s" #: bookwyrm/templates/snippets/goal_card.html:23 #, python-format @@ -2754,7 +2754,7 @@ msgstr "Ver %(size)s" #: bookwyrm/templates/user/user.html:47 msgid "View all books" -msgstr "" +msgstr "Ver todos los libros" #: bookwyrm/templates/user/user.html:59 #, python-format @@ -2813,12 +2813,12 @@ msgstr "Ya existe un usuario con ese nombre." #: bookwyrm/views/password.py:41 #, python-format msgid "A password reset link sent to %s" -msgstr "" +msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" #: venv/lib/python3.8/site-packages/_pytest/config/argparsing.py:442 #, python-format msgid "ambiguous option: %(option)s could match %(matches)s" -msgstr "" +msgstr "opción ambiguo: %(option)s pudiera coincidir con %(matches)s" #: venv/lib/python3.8/site-packages/django/contrib/messages/apps.py:7 #, fuzzy @@ -2828,27 +2828,27 @@ msgstr "Todos los mensajes" #: venv/lib/python3.8/site-packages/django/contrib/sitemaps/apps.py:7 msgid "Site Maps" -msgstr "" +msgstr "Mapas de sitio" #: venv/lib/python3.8/site-packages/django/contrib/staticfiles/apps.py:9 msgid "Static Files" -msgstr "" +msgstr "Archivos estáticos" #: venv/lib/python3.8/site-packages/django/contrib/syndication/apps.py:7 msgid "Syndication" -msgstr "" +msgstr "Sindicación" #: venv/lib/python3.8/site-packages/django/core/paginator.py:48 msgid "That page number is not an integer" -msgstr "" +msgstr "Ese numero de pagina no es un entero" #: venv/lib/python3.8/site-packages/django/core/paginator.py:50 msgid "That page number is less than 1" -msgstr "" +msgstr "Ese numero de pagina es menos que uno" #: venv/lib/python3.8/site-packages/django/core/paginator.py:55 msgid "That page contains no results" -msgstr "" +msgstr "Esa pagina no contiene resultados" #: venv/lib/python3.8/site-packages/django/core/validators.py:20 #, fuzzy @@ -2878,11 +2878,11 @@ msgstr "Dirección de correo electrónico:" #. Translators: "letters" means latin letters: a-z and A-Z. #: venv/lib/python3.8/site-packages/django/core/validators.py:230 msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." -msgstr "" +msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones" #: venv/lib/python3.8/site-packages/django/core/validators.py:237 msgid "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens." -msgstr "" +msgstr "Ingrese un “slug” válido que consiste de letras Unicode, numeros, guiones bajos, o guiones" #: venv/lib/python3.8/site-packages/django/core/validators.py:246 #: venv/lib/python3.8/site-packages/django/core/validators.py:266 @@ -2907,22 +2907,22 @@ msgstr "Dirección de correo electrónico:" #: venv/lib/python3.8/site-packages/django/core/validators.py:295 msgid "Enter only digits separated by commas." -msgstr "" +msgstr "Ingrese solo digitos separados por comas." #: venv/lib/python3.8/site-packages/django/core/validators.py:301 #, python-format msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "" +msgstr "Asegura que este valor es %(limit_value)s (es %(show_value)s)." #: venv/lib/python3.8/site-packages/django/core/validators.py:334 #, python-format msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "" +msgstr "Asegura que este valor es menor que o iguala a %(limit_value)s." #: venv/lib/python3.8/site-packages/django/core/validators.py:343 #, python-format msgid "Ensure this value is greater than or equal to %(limit_value)s." -msgstr "" +msgstr "Asegura que este valor es más que o que iguala a %(limit_value)s." #: venv/lib/python3.8/site-packages/django/core/validators.py:353 #, python-format @@ -2970,7 +2970,7 @@ msgstr[1] "" #: venv/lib/python3.8/site-packages/django/core/validators.py:461 #, python-format msgid "File extension “%(extension)s” is not allowed. Allowed extensions are: %(allowed_extensions)s." -msgstr "" +msgstr "No se permite la extensión de archivo “%(extension)s”. Extensiones permitidas son: %(allowed_extensions)s." #: venv/lib/python3.8/site-packages/django/core/validators.py:513 msgid "Null characters are not allowed." From ca63bd69477ea74080906f08b0acf84dfd6c009e Mon Sep 17 00:00:00 2001 From: reese Date: Wed, 21 Apr 2021 12:20:03 -0500 Subject: [PATCH 079/109] more translations --- locale/es/LC_MESSAGES/django.po | 333 +++++++++++++++----------------- 1 file changed, 159 insertions(+), 174 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index acefc2563..22b8ffb95 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -676,7 +676,7 @@ msgstr "Esta instancia está cerrada." #: bookwyrm/templates/discover/landing_layout.html:57 msgid "Thank you! Your request has been received." -msgstr "¡Gracias! Tu solicitación ha sido recibido." +msgstr "¡Gracias! Tu solicitud ha sido recibido." #: bookwyrm/templates/discover/landing_layout.html:60 msgid "Request an Invitation" @@ -771,7 +771,7 @@ msgstr "Aprenda más sobre esta ins #: bookwyrm/templates/email/invite/text_content.html:4 #, python-format msgid "You're invited to join %(site_name)s! Click the link below to create an account." -msgstr "Estás invitado a unirte con %(site_name)s! Haz clic en el enlace debajo para crear una cuenta." +msgstr "Estás invitado a unirte con %(site_name)s! Haz clic en el enlace a continuación para crear una cuenta." #: bookwyrm/templates/email/invite/text_content.html:8 #, fuzzy @@ -783,7 +783,7 @@ msgstr "Más sobre este sitio" #: bookwyrm/templates/email/password_reset/text_content.html:4 #, python-format msgid "You requested to reset your %(site_name)s password. Click the link below to set a new password and log in to your account." -msgstr "Tú solicitaste reestablecer tu %(site_name)s contraseña. Haz clic en el enlace debajo para establecer una nueva contraseña e ingresar a tu cuenta." +msgstr "Tú solicitaste reestablecer tu %(site_name)s contraseña. Haz clic en el enlace a continuación para establecer una nueva contraseña e ingresar a tu cuenta." #: bookwyrm/templates/email/password_reset/html_content.html:9 #: bookwyrm/templates/password_reset.html:4 @@ -1929,7 +1929,7 @@ msgstr "Invitaciones" #: bookwyrm/templates/settings/manage_invite_requests.html:23 msgid "Ignored Invite Requests" -msgstr "Solicitaciones de invitación ignoradas" +msgstr "Solicitudes de invitación ignoradas" #: bookwyrm/templates/settings/manage_invite_requests.html:35 #, fuzzy @@ -1992,11 +1992,11 @@ msgstr "Des-ignorar" #: bookwyrm/templates/settings/manage_invite_requests.html:108 msgid "Back to pending requests" -msgstr "Volver a las solicitaciones pendientes" +msgstr "Volver a las solicitudes pendientes" #: bookwyrm/templates/settings/manage_invite_requests.html:110 msgid "View ignored requests" -msgstr "Ver solicitaciones ignoradas" +msgstr "Ver solicitudes ignoradas" #: bookwyrm/templates/settings/manage_invites.html:21 msgid "Generate New Invite" @@ -2974,12 +2974,12 @@ msgstr "No se permite la extensión de archivo “%(extension)s”. Extensiones #: venv/lib/python3.8/site-packages/django/core/validators.py:513 msgid "Null characters are not allowed." -msgstr "" +msgstr "No se permiten caracteres nulos" #: venv/lib/python3.8/site-packages/django/db/models/base.py:1190 #: venv/lib/python3.8/site-packages/django/forms/models.py:760 msgid "and" -msgstr "" +msgstr "y" #: venv/lib/python3.8/site-packages/django/db/models/base.py:1192 #, fuzzy, python-format @@ -3001,7 +3001,7 @@ msgstr "Este estante está vacio." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:102 msgid "This field cannot be blank." -msgstr "" +msgstr "Este campo no puede ser vacio." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:103 #, fuzzy, python-format @@ -3014,31 +3014,31 @@ msgstr "Ya existe un usuario con ese nombre." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:107 #, python-format msgid "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." -msgstr "" +msgstr "%(field_label)s deben ser unicos por %(date_field_label)s %(lookup_type)s." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:126 #, python-format msgid "Field of type: %(field_type)s" -msgstr "" +msgstr "Campo de tipo: %(field_type)s" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:939 #, python-format msgid "“%(value)s” value must be either True or False." -msgstr "" +msgstr "“%(value)s” valor debe ser o verdadero o falso." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:940 #, python-format msgid "“%(value)s” value must be either True, False, or None." -msgstr "" +msgstr "%(value)s” valor debe ser o True, False, o None." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:942 msgid "Boolean (Either True or False)" -msgstr "" +msgstr "Booleano (O True O False)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:983 #, python-format msgid "String (up to %(max_length)s)" -msgstr "" +msgstr "Cadena (máximo de %(max_length)s caracteres)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1047 #, fuzzy @@ -3049,31 +3049,31 @@ msgstr "No invitaciónes activas" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1096 #, python-format msgid "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD format." -msgstr "" +msgstr "“%(value)s” valor tiene un formato de fecha inválido. Hay que estar de formato YYYY-MM-DD." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1098 #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1241 #, python-format msgid "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid date." -msgstr "" +msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD) pero la fecha es invalida." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1101 msgid "Date (without time)" -msgstr "" +msgstr "Fecha (sin la hora)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1239 #, python-format msgid "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format." -msgstr "" +msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1243 #, python-format msgid "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) but it is an invalid date/time." -msgstr "" +msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) pero es una fecha/hora invalida." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1247 msgid "Date (with time)" -msgstr "" +msgstr "Fecha (con la hora)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1395 #, fuzzy, python-format @@ -3090,7 +3090,7 @@ msgstr "Número de serie:" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1536 #, python-format msgid "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[.uuuuuu] format." -msgstr "" +msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato [DD] [[HH:]MM:]ss[.uuuuuu]." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1539 #, fuzzy @@ -3106,7 +3106,7 @@ msgstr "Dirección de correo electrónico:" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1612 msgid "File path" -msgstr "" +msgstr "Ruta de archivo" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1678 #, fuzzy, python-format @@ -3116,16 +3116,16 @@ msgstr "%(value)s no es un usuario válido" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1680 msgid "Floating point number" -msgstr "" +msgstr "Número de coma flotante" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1718 #, python-format msgid "“%(value)s” value must be an integer." -msgstr "" +msgstr "“%(value)s” valor debe ser un entero." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1720 msgid "Integer" -msgstr "" +msgstr "Entero" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1803 #, fuzzy @@ -3149,11 +3149,11 @@ msgstr "Dirección de correo electrónico:" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1931 #, python-format msgid "“%(value)s” value must be either None, True or False." -msgstr "" +msgstr "Valor debe ser o None, True, o False." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1933 msgid "Boolean (Either True, False or None)" -msgstr "" +msgstr "Booleano (O True, Falso, o None)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1976 #, fuzzy @@ -3176,37 +3176,37 @@ msgstr "No invitaciónes activas" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2016 #, python-format msgid "Slug (up to %(max_length)s)" -msgstr "" +msgstr "Slug (máximo de %(max_length)s)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2048 msgid "Small integer" -msgstr "" +msgstr "Entero pequeño" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2055 msgid "Text" -msgstr "" +msgstr "Texto" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2083 #, python-format msgid "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] format." -msgstr "" +msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato HH:MM[:ss[.uuuuuu]]." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2085 #, python-format msgid "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an invalid time." -msgstr "" +msgstr "“%(value)s” valor tiene el formato correcto (HH:MM[:ss[.uuuuuu]]) pero es una hora invalida." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2088 msgid "Time" -msgstr "" +msgstr "Tiempo" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2214 msgid "URL" -msgstr "" +msgstr "URL" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2236 msgid "Raw binary data" -msgstr "" +msgstr "Datos binarios sin procesar" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2301 #, fuzzy, python-format @@ -3216,11 +3216,11 @@ msgstr "%(value)s no es un usuario válido" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2303 msgid "Universally unique identifier" -msgstr "" +msgstr "Identificador universalmente único" #: venv/lib/python3.8/site-packages/django/db/models/fields/files.py:231 msgid "File" -msgstr "" +msgstr "Archivo" #: venv/lib/python3.8/site-packages/django/db/models/fields/files.py:379 #, fuzzy @@ -3230,20 +3230,20 @@ msgstr "Imagenes" #: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:18 msgid "A JSON object" -msgstr "" +msgstr "Un objeto JSON" #: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:20 msgid "Value must be valid JSON." -msgstr "" +msgstr "Valor debe ser JSON valido." #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:790 #, python-format msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "" +msgstr "%(model)s instancia con %(field)s %(value)r no existe." #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:792 msgid "Foreign Key (type determined by related field)" -msgstr "" +msgstr "Clave externa (tipo determinado por campo relacionado)" #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1045 #, fuzzy @@ -3316,15 +3316,15 @@ msgstr "Dirección de correo electrónico:" #: venv/lib/python3.8/site-packages/django/forms/fields.py:485 #, python-brace-format msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" +msgstr "El número de dias debe ser entre {min_days} y {max_days}." #: venv/lib/python3.8/site-packages/django/forms/fields.py:545 msgid "No file was submitted. Check the encoding type on the form." -msgstr "" +msgstr "No se aceptó ningun archivo. Verfica el tipo de codificación en el formulario." #: venv/lib/python3.8/site-packages/django/forms/fields.py:546 msgid "No file was submitted." -msgstr "" +msgstr "No se aceptó ningun archivo." #: venv/lib/python3.8/site-packages/django/forms/fields.py:547 #, fuzzy @@ -3341,18 +3341,18 @@ msgstr[1] "" #: venv/lib/python3.8/site-packages/django/forms/fields.py:552 msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "" +msgstr "Por favor, o envia un archivo o marca la casilla vacia, no los dos." #: venv/lib/python3.8/site-packages/django/forms/fields.py:613 msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." -msgstr "" +msgstr "Subir una imagen valida. El archivo que subiste o no fue imagen o fue corrupto." #: venv/lib/python3.8/site-packages/django/forms/fields.py:775 #: venv/lib/python3.8/site-packages/django/forms/fields.py:865 #: venv/lib/python3.8/site-packages/django/forms/models.py:1296 #, python-format msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "" +msgstr "Selecciona una opción valida. %(value)s no es una de las opciones disponibles." #: venv/lib/python3.8/site-packages/django/forms/fields.py:866 #: venv/lib/python3.8/site-packages/django/forms/fields.py:981 @@ -3364,7 +3364,7 @@ msgstr "Dirección de correo electrónico:" #: venv/lib/python3.8/site-packages/django/forms/fields.py:982 msgid "Enter a complete value." -msgstr "" +msgstr "Ingresa un valor completo." #: venv/lib/python3.8/site-packages/django/forms/fields.py:1198 #, fuzzy @@ -3381,16 +3381,16 @@ msgstr "Dirección de correo electrónico:" #. Translators: This is the default suffix added to form field labels #: venv/lib/python3.8/site-packages/django/forms/forms.py:78 msgid ":" -msgstr "" +msgstr ":" #: venv/lib/python3.8/site-packages/django/forms/forms.py:205 #, python-format msgid "(Hidden field %(name)s) %(error)s" -msgstr "" +msgstr "(Campo oculto %(name)s) %(error)s" #: venv/lib/python3.8/site-packages/django/forms/formsets.py:93 msgid "ManagementForm data is missing or has been tampered with" -msgstr "" +msgstr "Datos de ManagementForm está ausento o ha sido corrompido" #: venv/lib/python3.8/site-packages/django/forms/formsets.py:345 #, python-format @@ -3408,35 +3408,38 @@ msgstr[1] "" #: venv/lib/python3.8/site-packages/django/forms/formsets.py:379 #: venv/lib/python3.8/site-packages/django/forms/formsets.py:386 +#, fuzzy +# TODO cc @mouse is this a verb or noun msgid "Order" -msgstr "" +msgstr "Pedir" # if verb +msgstr "Pedido" # if noun #: venv/lib/python3.8/site-packages/django/forms/models.py:755 #, python-format msgid "Please correct the duplicate data for %(field)s." -msgstr "" +msgstr "Por favor corrige los datos duplicados en %(field)s." #: venv/lib/python3.8/site-packages/django/forms/models.py:759 #, python-format msgid "Please correct the duplicate data for %(field)s, which must be unique." -msgstr "" +msgstr "Por favor corrige los datos duplicados en %(field)s, los cuales deben ser unicos." #: venv/lib/python3.8/site-packages/django/forms/models.py:765 #, python-format msgid "Please correct the duplicate data for %(field_name)s which must be unique for the %(lookup)s in %(date_field)s." -msgstr "" +msgstr "Por favor corrige los datos duplicados en %(field_name)s los cuales deben ser unicos por el %(lookup)s en %(date_field)s." #: venv/lib/python3.8/site-packages/django/forms/models.py:774 msgid "Please correct the duplicate values below." -msgstr "" +msgstr "Por favor corrige los valores duplicados a continuación." #: venv/lib/python3.8/site-packages/django/forms/models.py:1096 msgid "The inline value did not match the parent instance." -msgstr "" +msgstr "El valor en línea no empareja la instancia progenitor." #: venv/lib/python3.8/site-packages/django/forms/models.py:1180 msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" +msgstr "Selecciona una opción válida. Esa opción no es una de las opciones disponibles." #: venv/lib/python3.8/site-packages/django/forms/models.py:1298 #, fuzzy, python-format @@ -3447,11 +3450,11 @@ msgstr "%(value)s no es un usuario válido" #: venv/lib/python3.8/site-packages/django/forms/utils.py:167 #, python-format msgid "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it may be ambiguous or it may not exist." -msgstr "" +msgstr "%(datetime)s no se pudo interpretar en la zona horaria %(current_timezone)s; puede ser ambiguo o puede que no exista." #: venv/lib/python3.8/site-packages/django/forms/widgets.py:398 msgid "Clear" -msgstr "" +msgstr "Borrar" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:399 #, fuzzy @@ -3467,20 +3470,20 @@ msgstr "Cambiar estante" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:709 msgid "Unknown" -msgstr "" +msgstr "Desconocido" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:710 msgid "Yes" -msgstr "" +msgstr "Sí" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:711 msgid "No" -msgstr "" +msgstr "No" #. Translators: Please do not add spaces around commas. #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:790 msgid "yes,no,maybe" -msgstr "" +msgstr "sí,no,quizás" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:819 #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:836 @@ -3493,430 +3496,412 @@ msgstr[1] "" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:838 #, python-format msgid "%s KB" -msgstr "" +msgstr "%s KB" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:840 #, python-format msgid "%s MB" -msgstr "" +msgstr "%s MB" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:842 #, python-format msgid "%s GB" -msgstr "" +msgstr "%s GB" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:844 #, python-format msgid "%s TB" -msgstr "" +msgstr "%s TB" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:846 #, python-format msgid "%s PB" -msgstr "" +msgstr "%s PB" #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:65 msgid "p.m." -msgstr "" +msgstr "p.m." #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:66 msgid "a.m." -msgstr "" +msgstr "a.m." #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:71 msgid "PM" -msgstr "" +msgstr "PM" #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:72 msgid "AM" -msgstr "" +msgstr "AM" #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:149 msgid "midnight" -msgstr "" +msgstr "medianoche" #: venv/lib/python3.8/site-packages/django/utils/dateformat.py:151 msgid "noon" -msgstr "" +msgstr "mediodia" #: venv/lib/python3.8/site-packages/django/utils/dates.py:6 #: venv/lib/python3.8/site-packages/tornado/locale.py:295 msgid "Monday" -msgstr "" +msgstr "Lunes" #: venv/lib/python3.8/site-packages/django/utils/dates.py:6 #: venv/lib/python3.8/site-packages/tornado/locale.py:296 msgid "Tuesday" -msgstr "" +msgstr "Martes" #: venv/lib/python3.8/site-packages/django/utils/dates.py:6 #: venv/lib/python3.8/site-packages/tornado/locale.py:297 msgid "Wednesday" -msgstr "" +msgstr "Miercoles" #: venv/lib/python3.8/site-packages/django/utils/dates.py:6 #: venv/lib/python3.8/site-packages/tornado/locale.py:298 msgid "Thursday" -msgstr "" +msgstr "Jueves" #: venv/lib/python3.8/site-packages/django/utils/dates.py:6 #: venv/lib/python3.8/site-packages/tornado/locale.py:299 msgid "Friday" -msgstr "" +msgstr "Viernes" #: venv/lib/python3.8/site-packages/django/utils/dates.py:7 #: venv/lib/python3.8/site-packages/tornado/locale.py:300 msgid "Saturday" -msgstr "" +msgstr "Sábado" #: venv/lib/python3.8/site-packages/django/utils/dates.py:7 #: venv/lib/python3.8/site-packages/tornado/locale.py:301 msgid "Sunday" -msgstr "" +msgstr "Domino" #: venv/lib/python3.8/site-packages/django/utils/dates.py:10 msgid "Mon" -msgstr "" +msgstr "Lun" #: venv/lib/python3.8/site-packages/django/utils/dates.py:10 msgid "Tue" -msgstr "" +msgstr "Mar" #: venv/lib/python3.8/site-packages/django/utils/dates.py:10 msgid "Wed" -msgstr "" +msgstr "Mie" #: venv/lib/python3.8/site-packages/django/utils/dates.py:10 msgid "Thu" -msgstr "" +msgstr "Jue" #: venv/lib/python3.8/site-packages/django/utils/dates.py:10 msgid "Fri" -msgstr "" +msgstr "Vie" #: venv/lib/python3.8/site-packages/django/utils/dates.py:11 -#, fuzzy -#| msgid "Status" msgid "Sat" -msgstr "Status" +msgstr "Sáb" #: venv/lib/python3.8/site-packages/django/utils/dates.py:11 msgid "Sun" -msgstr "" +msgstr "Dom" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:281 msgid "January" -msgstr "" +msgstr "Enero" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:282 msgid "February" -msgstr "" +msgstr "Febrero" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:283 -#, fuzzy -#| msgid "Search" msgid "March" -msgstr "Buscar" +msgstr "Marzo" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:284 msgid "April" -msgstr "" +msgstr "Abril" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:285 msgid "May" -msgstr "" +msgstr "Mayo" #: venv/lib/python3.8/site-packages/django/utils/dates.py:14 #: venv/lib/python3.8/site-packages/tornado/locale.py:286 msgid "June" -msgstr "" +msgstr "Junio" #: venv/lib/python3.8/site-packages/django/utils/dates.py:15 #: venv/lib/python3.8/site-packages/tornado/locale.py:287 msgid "July" -msgstr "" +msgstr "Julio" #: venv/lib/python3.8/site-packages/django/utils/dates.py:15 #: venv/lib/python3.8/site-packages/tornado/locale.py:288 msgid "August" -msgstr "" +msgstr "Agosto" #: venv/lib/python3.8/site-packages/django/utils/dates.py:15 #: venv/lib/python3.8/site-packages/tornado/locale.py:289 -#, fuzzy -#| msgid "Series number:" msgid "September" -msgstr "Número de serie:" +msgstr "Septiembre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:15 #: venv/lib/python3.8/site-packages/tornado/locale.py:290 msgid "October" -msgstr "" +msgstr "Octubre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:15 #: venv/lib/python3.8/site-packages/tornado/locale.py:291 msgid "November" -msgstr "" +msgstr "Noviembre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:16 #: venv/lib/python3.8/site-packages/tornado/locale.py:292 -#, fuzzy -#| msgid "Series number:" msgid "December" -msgstr "Número de serie:" +msgstr "Diciembre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "jan" -msgstr "" +msgstr "ene" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "feb" -msgstr "" +msgstr "feb" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "mar" -msgstr "" +msgstr "mar" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "apr" -msgstr "" +msgstr "abr" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "may" -msgstr "" +msgstr "may" #: venv/lib/python3.8/site-packages/django/utils/dates.py:19 msgid "jun" -msgstr "" +msgstr "jun" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "jul" -msgstr "" +msgstr "jul" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "aug" -msgstr "" +msgstr "ago" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "sep" -msgstr "" +msgstr "sep" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "oct" -msgstr "" +msgstr "oct" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "nov" -msgstr "" +msgstr "nov" #: venv/lib/python3.8/site-packages/django/utils/dates.py:20 msgid "dec" -msgstr "" +msgstr "dic" #: venv/lib/python3.8/site-packages/django/utils/dates.py:23 msgctxt "abbrev. month" msgid "Jan." -msgstr "" +msgstr "en." #: venv/lib/python3.8/site-packages/django/utils/dates.py:24 msgctxt "abbrev. month" msgid "Feb." -msgstr "" +msgstr "feb." #: venv/lib/python3.8/site-packages/django/utils/dates.py:25 -#, fuzzy -#| msgid "Search" msgctxt "abbrev. month" msgid "March" -msgstr "Buscar" +msgstr "mzo." #: venv/lib/python3.8/site-packages/django/utils/dates.py:26 msgctxt "abbrev. month" msgid "April" -msgstr "" +msgstr "abr." #: venv/lib/python3.8/site-packages/django/utils/dates.py:27 msgctxt "abbrev. month" msgid "May" -msgstr "" +msgstr "my." #: venv/lib/python3.8/site-packages/django/utils/dates.py:28 msgctxt "abbrev. month" msgid "June" -msgstr "" +msgstr "jun." #: venv/lib/python3.8/site-packages/django/utils/dates.py:29 msgctxt "abbrev. month" msgid "July" -msgstr "" +msgstr "jul." #: venv/lib/python3.8/site-packages/django/utils/dates.py:30 msgctxt "abbrev. month" msgid "Aug." -msgstr "" +msgstr "agto." #: venv/lib/python3.8/site-packages/django/utils/dates.py:31 msgctxt "abbrev. month" msgid "Sept." -msgstr "" +msgstr "set." #: venv/lib/python3.8/site-packages/django/utils/dates.py:32 msgctxt "abbrev. month" msgid "Oct." -msgstr "" +msgstr "oct." #: venv/lib/python3.8/site-packages/django/utils/dates.py:33 msgctxt "abbrev. month" msgid "Nov." -msgstr "" +msgstr "nov." #: venv/lib/python3.8/site-packages/django/utils/dates.py:34 msgctxt "abbrev. month" msgid "Dec." -msgstr "" +msgstr "dic." #: venv/lib/python3.8/site-packages/django/utils/dates.py:37 msgctxt "alt. month" msgid "January" -msgstr "" +msgstr "Enero" #: venv/lib/python3.8/site-packages/django/utils/dates.py:38 msgctxt "alt. month" msgid "February" -msgstr "" +msgstr "Febrero" #: venv/lib/python3.8/site-packages/django/utils/dates.py:39 -#, fuzzy -#| msgid "Search" msgctxt "alt. month" msgid "March" -msgstr "Buscar" +msgstr "Marzo" #: venv/lib/python3.8/site-packages/django/utils/dates.py:40 msgctxt "alt. month" msgid "April" -msgstr "" +msgstr "Abril" #: venv/lib/python3.8/site-packages/django/utils/dates.py:41 msgctxt "alt. month" msgid "May" -msgstr "" +msgstr "Mayo" #: venv/lib/python3.8/site-packages/django/utils/dates.py:42 msgctxt "alt. month" msgid "June" -msgstr "" +msgstr "Junio" #: venv/lib/python3.8/site-packages/django/utils/dates.py:43 msgctxt "alt. month" msgid "July" -msgstr "" +msgstr "Julio" #: venv/lib/python3.8/site-packages/django/utils/dates.py:44 msgctxt "alt. month" msgid "August" -msgstr "" +msgstr "Agosto" #: venv/lib/python3.8/site-packages/django/utils/dates.py:45 -#, fuzzy -#| msgid "Series number:" msgctxt "alt. month" msgid "September" -msgstr "Número de serie:" +msgstr "Septiembre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:46 msgctxt "alt. month" msgid "October" -msgstr "" +msgstr "Octubre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:47 msgctxt "alt. month" msgid "November" -msgstr "" +msgstr "Noviembre" #: venv/lib/python3.8/site-packages/django/utils/dates.py:48 -#, fuzzy -#| msgid "Series number:" msgctxt "alt. month" msgid "December" -msgstr "Número de serie:" +msgstr "Diciembre" #: venv/lib/python3.8/site-packages/django/utils/ipv6.py:8 -#, fuzzy -#| msgid "Email address:" msgid "This is not a valid IPv6 address." -msgstr "Dirección de correo electrónico:" +msgstr "Esta no es una valida dirección IPv6." #: venv/lib/python3.8/site-packages/django/utils/text.py:70 #, python-format msgctxt "String to return when truncating text" msgid "%(truncated_text)s…" -msgstr "" +msgstr "%(truncated_text)s…" #: venv/lib/python3.8/site-packages/django/utils/text.py:236 msgid "or" -msgstr "" +msgstr "o" #. Translators: This string is used as a separator between list elements #: venv/lib/python3.8/site-packages/django/utils/text.py:255 #: venv/lib/python3.8/site-packages/django/utils/timesince.py:83 msgid ", " -msgstr "" +msgstr ", " #: venv/lib/python3.8/site-packages/django/utils/timesince.py:9 #, python-format msgid "%d year" msgid_plural "%d years" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d año" +msgstr[1] "%d años" #: venv/lib/python3.8/site-packages/django/utils/timesince.py:10 #, python-format msgid "%d month" msgid_plural "%d months" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d mes" +msgstr[1] "%d meses" #: venv/lib/python3.8/site-packages/django/utils/timesince.py:11 #, python-format msgid "%d week" msgid_plural "%d weeks" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d semana" +msgstr[1] "%d semanas" #: venv/lib/python3.8/site-packages/django/utils/timesince.py:12 #, python-format msgid "%d day" msgid_plural "%d days" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d día" +msgstr[1] "%d días" #: venv/lib/python3.8/site-packages/django/utils/timesince.py:13 #, python-format msgid "%d hour" msgid_plural "%d hours" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d hora" +msgstr[1] "%d horas" #: venv/lib/python3.8/site-packages/django/utils/timesince.py:14 #, python-format msgid "%d minute" msgid_plural "%d minutes" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" #: venv/lib/python3.8/site-packages/django/views/csrf.py:110 msgid "Forbidden" -msgstr "" +msgstr "Prohibido" #: venv/lib/python3.8/site-packages/django/views/csrf.py:111 msgid "CSRF verification failed. Request aborted." -msgstr "" +msgstr "Se falló la verificación CSRF. Se abortó la solicitud." #: venv/lib/python3.8/site-packages/django/views/csrf.py:115 msgid "You are seeing this message because this HTTPS site requires a “Referer header” to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties." From e6bd89e10bff0b7d1fac95c3fe94e4e8c6ed581e Mon Sep 17 00:00:00 2001 From: reese Date: Wed, 21 Apr 2021 14:54:27 -0500 Subject: [PATCH 080/109] more translations --- locale/es/LC_MESSAGES/django.po | 159 +++++++++++++++++--------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 22b8ffb95..5b53b3ab8 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -900,15 +900,15 @@ msgstr "%(year)s Meta de lectura" #, python-format msgid "%(mutuals)s follower you follow" msgid_plural "%(mutuals)s followers you follow" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(mutuals)s seguidor que sigues" +msgstr[1] "%(mutuals)s seguidores que sigues" #: bookwyrm/templates/feed/suggested_users.html:19 #, python-format msgid "%(shared_books)s book on your shelves" msgid_plural "%(shared_books)s books on your shelves" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(shared_books)s libro en tus estantes" +msgstr[1] "%(shared_books)s libros en tus estantes" #: bookwyrm/templates/get_started/book_preview.html:6 #, fuzzy, python-format @@ -2305,8 +2305,8 @@ msgstr "No calificación" #, python-format msgid "%(rating)s star" msgid_plural "%(rating)s stars" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(rating)s estrella" +msgstr[1] "%(rating)s estrellas" #: bookwyrm/templates/snippets/generated_status/goal.html:1 #, python-format @@ -2327,8 +2327,8 @@ msgstr[1] "%(title)s por " #, python-format msgid "Review of \"%(book_title)s\" (%(display_rating)s star): %(review_title)s" msgid_plural "Review of \"%(book_title)s\" (%(display_rating)s stars): %(review_title)s" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Reseña de \"%(book_title)s\" (%(display_rating)s estrella): %(review_title)s" +msgstr[1] "Reseña de \"%(book_title)s\" (%(display_rating)s estrellas): %(review_title)s" #: bookwyrm/templates/snippets/generated_status/review_pure_name.html:8 #, python-format @@ -2928,15 +2928,15 @@ msgstr "Asegura que este valor es más que o que iguala a %(limit_value)s." #, python-format msgid "Ensure this value has at least %(limit_value)d character (it has %(show_value)d)." msgid_plural "Ensure this value has at least %(limit_value)d characters (it has %(show_value)d)." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que este valor tiene por lo menos %(limit_value)d carácter. (Tiene %(show_value)d).)" +msgstr[1] "Verifica que este valor tiene por lo menos %(limit_value)d caracteres. (Tiene %(show_value)d).)" #: venv/lib/python3.8/site-packages/django/core/validators.py:368 #, python-format msgid "Ensure this value has at most %(limit_value)d character (it has %(show_value)d)." msgid_plural "Ensure this value has at most %(limit_value)d characters (it has %(show_value)d)." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que este valor tiene a lo sumo %(limit_value)d carácter. (Tiene %(show_value)d).)" +msgstr[1] "Verifica que este valor tiene a lo sumo %(limit_value)d caracteres. (Tiene %(show_value)d).)" #: venv/lib/python3.8/site-packages/django/core/validators.py:387 #: venv/lib/python3.8/site-packages/django/forms/fields.py:292 @@ -2950,22 +2950,23 @@ msgstr "Número de serie:" #, python-format msgid "Ensure that there are no more than %(max)s digit in total." msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que no hay más que %(max)s digito en total." +msgstr[1] "Verifica que no hay más que %(max)s digitos en total." #: venv/lib/python3.8/site-packages/django/core/validators.py:394 #, python-format +# is msgid "Ensure that there are no more than %(max)s decimal place." msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que no hay más que %(max)s cifra decimal." +msgstr[1] "Verifica que no hay más que %(max)s cifras decimales." #: venv/lib/python3.8/site-packages/django/core/validators.py:399 #, python-format msgid "Ensure that there are no more than %(max)s digit before the decimal point." msgid_plural "Ensure that there are no more than %(max)s digits before the decimal point." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que no hay más que %(max)s digito antes de la coma decimal." +msgstr[1] "Verifica que no hay más que %(max)s digitos antes de la coma decimal." #: venv/lib/python3.8/site-packages/django/core/validators.py:461 #, python-format @@ -3336,8 +3337,8 @@ msgstr "Este estante está vacio." #, python-format msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." msgid_plural "Ensure this filename has at most %(max)d characters (it has %(length)d)." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Verifica que este nombre de archivo no tiene más que %(max)d carácter. (Tiene %(length)d)." +msgstr[1] "Verifica que este nombre de archivo no tiene más que %(max)d caracteres. (Tiene %(length)d)." #: venv/lib/python3.8/site-packages/django/forms/fields.py:552 msgid "Please either submit a file or check the clear checkbox, not both." @@ -3396,15 +3397,15 @@ msgstr "Datos de ManagementForm está ausento o ha sido corrompido" #, python-format msgid "Please submit %d or fewer forms." msgid_plural "Please submit %d or fewer forms." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Por favor, enviar %d o menos formularios." +msgstr[1] "Por favor, enviar %d o menos formularios." #: venv/lib/python3.8/site-packages/django/forms/formsets.py:352 #, python-format msgid "Please submit %d or more forms." msgid_plural "Please submit %d or more forms." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Por favor, enviar %d o más formularios." +msgstr[1] "Por favor, enviar %d o más formularios." #: venv/lib/python3.8/site-packages/django/forms/formsets.py:379 #: venv/lib/python3.8/site-packages/django/forms/formsets.py:386 @@ -3490,8 +3491,8 @@ msgstr "sí,no,quizás" #, python-format msgid "%(size)d byte" msgid_plural "%(size)d bytes" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" #: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:838 #, python-format @@ -3905,65 +3906,65 @@ msgstr "Se falló la verificación CSRF. Se abortó la solicitud." #: venv/lib/python3.8/site-packages/django/views/csrf.py:115 msgid "You are seeing this message because this HTTPS site requires a “Referer header” to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties." -msgstr "" +msgstr "Estás viendo este mensaje porque este sitio HTTPS requiere que tu navegador Web envie un “Referer header”, pero no se la envió. Esta cabecedera se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." #: venv/lib/python3.8/site-packages/django/views/csrf.py:120 msgid "If you have configured your browser to disable “Referer” headers, please re-enable them, at least for this site, or for HTTPS connections, or for “same-origin” requests." -msgstr "" +msgstr "Si has configurado su navegador para deshabilitar las cabecederas “Referer”, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " #: venv/lib/python3.8/site-packages/django/views/csrf.py:124 msgid "If you are using the tag or including the “Referrer-Policy: no-referrer” header, please remove them. The CSRF protection requires the “Referer” header to do strict referer checking. If you’re concerned about privacy, use alternatives like for links to third-party sites." -msgstr "" +msgstr "Si estás usando la eqtigueta o estás incluyendo la cabecedera “Referrer-Policy: no-referrer”, quitalas por favor. La protección CSRF require la cabecedera “Referer” para hacer verficación “strict referer“. Si te preocupa la privacidad, utiliza alternativas como para sitios de terceros." #: venv/lib/python3.8/site-packages/django/views/csrf.py:132 msgid "You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties." -msgstr "" +msgstr "Estás viendo este mensaje porque este sitio requiere un cookie CSRF cuando se envie formularios. Este cookie se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." #: venv/lib/python3.8/site-packages/django/views/csrf.py:137 msgid "If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for “same-origin” requests." -msgstr "" +msgstr "Si has configurado su navegador para deshabilitar los cookies, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " #: venv/lib/python3.8/site-packages/django/views/csrf.py:142 msgid "More information is available with DEBUG=True." -msgstr "" +msgstr "Más información es disponible con DEBUG=True." #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:41 msgid "No year specified" -msgstr "" +msgstr "Ningun año fue especificado" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:61 #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:111 #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:208 msgid "Date out of range" -msgstr "" +msgstr "Fecha fuera de rango" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:90 msgid "No month specified" -msgstr "" +msgstr "Ningun mes fue especificado" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:142 msgid "No day specified" -msgstr "" +msgstr "Ningun día fue especificado" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:188 msgid "No week specified" -msgstr "" +msgstr "Ninguna semana fue especificado" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:338 #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:367 #, python-format msgid "No %(verbose_name_plural)s available" -msgstr "" +msgstr "No %(verbose_name_plural)s disponible" #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:589 #, python-format msgid "Future %(verbose_name_plural)s not available because %(class_name)s.allow_future is False." -msgstr "" +msgstr "%(verbose_name_plural)s del futuro no está disponible porque %(class_name)s.allow_future es False." #: venv/lib/python3.8/site-packages/django/views/generic/dates.py:623 #, python-format msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "" +msgstr "Cadena de fecha invalida “%(datestr)s” dado el formato “%(format)s”" #: venv/lib/python3.8/site-packages/django/views/generic/detail.py:54 #, fuzzy, python-format @@ -3973,21 +3974,21 @@ msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query) #: venv/lib/python3.8/site-packages/django/views/generic/list.py:67 msgid "Page is not “last”, nor can it be converted to an int." -msgstr "" +msgstr "Página no es “last”, ni puede ser convertido en un int." #: venv/lib/python3.8/site-packages/django/views/generic/list.py:72 #, python-format msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "" +msgstr "Página invalida (%(page_number)s): %(message)s" #: venv/lib/python3.8/site-packages/django/views/generic/list.py:154 #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" +msgstr "Lista vacia y “%(class_name)s.allow_empty” es False." #: venv/lib/python3.8/site-packages/django/views/static.py:40 msgid "Directory indexes are not allowed here." -msgstr "" +msgstr "Indices directorios no se permiten aquí." #: venv/lib/python3.8/site-packages/django/views/static.py:42 #, fuzzy, python-format @@ -3998,41 +3999,41 @@ msgstr "%(value)s no es un usuario válido" #: venv/lib/python3.8/site-packages/django/views/static.py:80 #, python-format msgid "Index of %(directory)s" -msgstr "" +msgstr "Indice de %(directory)s" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:7 msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "" +msgstr "Django: el estructura Web para perfeccionistas con fechas límites." #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:346 #, python-format msgid "View release notes for Django %(version)s" -msgstr "" +msgstr "Ver notas de lanzamiento por Django %(version)s" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:368 msgid "The install worked successfully! Congratulations!" -msgstr "" +msgstr "¡La instalación fue exitoso! ¡Felicidades!" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:369 #, python-format msgid "You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs." -msgstr "" +msgstr "Estás viendo esta pagina porque DEBUG=True está en tu archivo de configuración y no has configurado ningún URL." #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:384 msgid "Django Documentation" -msgstr "" +msgstr "Documentación de Django" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:385 msgid "Topics, references, & how-to’s" -msgstr "" +msgstr "Tópicos, referencias, & instrucciones paso-a-paso" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:396 msgid "Tutorial: A Polling App" -msgstr "" +msgstr "Tutorial: Una aplicación polling" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:397 msgid "Get started with Django" -msgstr "" +msgstr "Empezar con Django" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:408 #, fuzzy @@ -4042,111 +4043,119 @@ msgstr "Comentario" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:409 msgid "Connect, get help, or contribute" -msgstr "" +msgstr "Conectarse, encontrar ayuda, o contribuir" #: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1301 #, python-format msgid "Attempting to connect to qpid with SASL mechanism %s" -msgstr "" +msgstr "Intentando conectar con qpid con mecanismo SASL %s" #: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1306 #, python-format msgid "Connected to qpid with SASL mechanism %s" -msgstr "" +msgstr "Conectado con qpid con mecanismo SASL %s" #: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1324 #, python-format msgid "Unable to connect to qpid with SASL mechanism %s" -msgstr "" +msgstr "No se pudo conectar con qpid con mecanismo SASL %s" #: venv/lib/python3.8/site-packages/tornado/locale.py:371 msgid "1 second ago" -msgstr "" +msgstr "Hace 1 segundo" #: venv/lib/python3.8/site-packages/tornado/locale.py:377 msgid "1 minute ago" -msgstr "" +msgstr "Hace 1 minuto" #: venv/lib/python3.8/site-packages/tornado/locale.py:382 msgid "1 hour ago" -msgstr "" +msgstr "Hace 1 hora" #: venv/lib/python3.8/site-packages/tornado/locale.py:385 #, python-format msgid "%(time)s" -msgstr "" +msgstr "%(time)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:387 msgid "yesterday" -msgstr "" +msgstr "ayer" #: venv/lib/python3.8/site-packages/tornado/locale.py:387 #, python-format +# TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock +# a working clock is broken twice a day! msgid "yesterday at %(time)s" -msgstr "" +msgstr "ayer a las %(time)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:389 #, python-format msgid "%(weekday)s" -msgstr "" +msgstr "%(weekday)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:389 #, python-format +# TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock +# a working clock is broken twice a day! msgid "%(weekday)s at %(time)s" -msgstr "" +msgstr "%(weekday)s a las %(time)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:392 #: venv/lib/python3.8/site-packages/tornado/locale.py:445 #, python-format msgid "%(month_name)s %(day)s" -msgstr "" +msgstr "%(day)s %(month_name)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:394 #, python-format +# TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock +# a working clock is broken twice a day! msgid "%(month_name)s %(day)s at %(time)s" -msgstr "" +msgstr "%(day)s %(month_name)s a las %(time)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:399 #, python-format msgid "%(month_name)s %(day)s, %(year)s" -msgstr "" +msgstr "%(day)s %(month_name)s, %(year)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:401 #, python-format +# TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock +# a working clock is broken twice a day! msgid "%(month_name)s %(day)s, %(year)s at %(time)s" -msgstr "" +msgstr "%(day)s %(month_name)s, %(year)s a las %(time)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:439 #, python-format msgid "%(weekday)s, %(month_name)s %(day)s" -msgstr "" +msgstr "%(weekday)s, %(day)s %(month_name)s" #: venv/lib/python3.8/site-packages/tornado/locale.py:462 #, python-format msgid "%(commas)s and %(last)s" -msgstr "" +msgstr "%(commas)s y %(last)s" #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:68 msgctxt "law" msgid "right" -msgstr "" +msgstr "justo" #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:69 msgctxt "good" msgid "right" -msgstr "" +msgstr "correcto" #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:71 #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:74 msgctxt "organization" msgid "club" -msgstr "" +msgstr "club" #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:76 #: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:77 msgctxt "stick" msgid "club" -msgstr "" +msgstr "garrote" #, fuzzy #~| msgid "Started" From c8de7890c69b94427961a9a910c1c9efcd1b912a Mon Sep 17 00:00:00 2001 From: reese Date: Wed, 21 Apr 2021 15:37:59 -0500 Subject: [PATCH 081/109] finally finished --- locale/es/LC_MESSAGES/django.po | 582 ++++++++------------------------ 1 file changed, 148 insertions(+), 434 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 5b53b3ab8..2fbf981c0 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -19,10 +19,8 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: bookwyrm/forms.py:226 -#, fuzzy -#| msgid "A user with that username already exists." msgid "A user with this email already exists." -msgstr "Ya existe un usuario con ese nombre." +msgstr "Ya existe un usuario con ese correo electrónico." #: bookwyrm/forms.py:240 msgid "One Day" @@ -164,10 +162,8 @@ msgid "Add cover" msgstr "Agregar portada" #: bookwyrm/templates/book/book.html:53 -#, fuzzy -#| msgid "Failed to load" msgid "Failed to load cover" -msgstr "Se falló a cargar" +msgstr "No se pudo cargar la portada" #: bookwyrm/templates/book/book.html:62 msgid "ISBN:" @@ -278,10 +274,8 @@ msgid "Lists" msgstr "Listas" #: bookwyrm/templates/book/book.html:213 -#, fuzzy -#| msgid "Go to list" msgid "Add to list" -msgstr "Irse a lista" +msgstr "Agregar a lista" #: bookwyrm/templates/book/book.html:223 #: bookwyrm/templates/book/cover_modal.html:31 @@ -295,10 +289,8 @@ msgstr "lo calificó con" #: bookwyrm/templates/book/cover_modal.html:17 #: bookwyrm/templates/book/edit_book.html:175 -#, fuzzy -#| msgid "Add cover" msgid "Upload cover:" -msgstr "Agregar portada:" +msgstr "Subir portada:" #: bookwyrm/templates/book/cover_modal.html:23 #: bookwyrm/templates/book/edit_book.html:181 @@ -307,15 +299,11 @@ msgstr "Agregar portada de url:" #: bookwyrm/templates/book/edit_book.html:5 #: bookwyrm/templates/book/edit_book.html:11 -#, fuzzy, python-format -#| msgid "Editions of %(book_title)s" msgid "Edit \"%(book_title)s\"" -msgstr "Ediciones de %(book_title)s" +msgstr "Editar \"%(book_title)s\"" #: bookwyrm/templates/book/edit_book.html:5 #: bookwyrm/templates/book/edit_book.html:13 -#, fuzzy -#| msgid "Add Books" msgid "Add Book" msgstr "Agregar libro" @@ -344,10 +332,8 @@ msgid "Is \"%(name)s\" an existing author?" msgstr "¿Es \"%(name)s\" un autor ya existente?" #: bookwyrm/templates/book/edit_book.html:52 -#, fuzzy, python-format -#| msgid "Start \"%(book_title)s\"" msgid "Author of %(book_title)s" -msgstr "Empezar \"%(book_title)s\"" +msgstr "Autor de %(book_title)s" #: bookwyrm/templates/book/edit_book.html:55 msgid "This is a new author" @@ -398,10 +384,8 @@ msgid "Series number:" msgstr "Número de serie:" #: bookwyrm/templates/book/edit_book.html:123 -#, fuzzy -#| msgid "Published" msgid "Publisher:" -msgstr "Publicado" +msgstr "Editorial:" #: bookwyrm/templates/book/edit_book.html:125 msgid "Separate multiple publishers with commas." @@ -416,22 +400,16 @@ msgid "Published date:" msgstr "Fecha de publicación:" #: bookwyrm/templates/book/edit_book.html:149 -#, fuzzy -#| msgid "Author" msgid "Authors" -msgstr "Autor/Autora" +msgstr "Autores" #: bookwyrm/templates/book/edit_book.html:155 -#, fuzzy, python-format -#| msgid "Added by %(username)s" msgid "Remove %(name)s" -msgstr "Agregado por %(username)s" +msgstr "Eliminar %(name)s" #: bookwyrm/templates/book/edit_book.html:160 -#, fuzzy -#| msgid "Edit Author" msgid "Add Authors:" -msgstr "Editar Autor/Autora" +msgstr "Agregar Autores:" #: bookwyrm/templates/book/edit_book.html:161 msgid "John Doe, Jane Smith" @@ -502,10 +480,8 @@ msgid "%(pages)s pages" msgstr "%(pages)s páginas" #: bookwyrm/templates/book/publisher_info.html:13 -#, fuzzy, python-format -#| msgid "%(pages)s pages" msgid "%(languages)s language" -msgstr "%(pages)s páginas" +msgstr "idioma %(languages)s" #: bookwyrm/templates/book/publisher_info.html:18 #, python-format @@ -513,10 +489,8 @@ msgid "Published %(date)s by %(publisher)s." msgstr "Publicado %(date)s por %(publisher)s." #: bookwyrm/templates/book/publisher_info.html:20 -#, fuzzy, python-format -#| msgid "Published date:" msgid "Published %(date)s" -msgstr "Fecha de publicación:" +msgstr "Publicado %(date)s" #: bookwyrm/templates/book/publisher_info.html:22 #, python-format @@ -532,28 +506,20 @@ msgid "Close" msgstr "Cerrar" #: bookwyrm/templates/compose.html:5 bookwyrm/templates/compose.html:8 -#, fuzzy -#| msgid "Boost status" msgid "Compose status" -msgstr "Status de respaldo" +msgstr "Componer status" #: bookwyrm/templates/directory/community_filter.html:5 -#, fuzzy -#| msgid "Comment" msgid "Community" -msgstr "Comentario" +msgstr "Comunidad" #: bookwyrm/templates/directory/community_filter.html:8 -#, fuzzy -#| msgid "Max uses" msgid "Local users" -msgstr "Número máximo de usos" +msgstr "Usuarios locales" #: bookwyrm/templates/directory/community_filter.html:12 -#, fuzzy -#| msgid "Federated" msgid "Federated community" -msgstr "Federalizado" +msgstr "Comunidad federalizada" #: bookwyrm/templates/directory/directory.html:6 #: bookwyrm/templates/directory/directory.html:11 @@ -566,10 +532,8 @@ msgid "Make your profile discoverable to other BookWyrm users." msgstr "Haz que tu perfil sea reconocible a otros usarios de BookWyrm." #: bookwyrm/templates/directory/directory.html:26 -#, fuzzy, python-format -#| msgid "You can set or change your reading goal any time from your profile page" msgid "You can opt-out at any time in your profile settings." -msgstr "Puedes establecer o cambiar tu meta de lectura en cualquier momento que desees desde tu perfil" +msgstr "Puedes optar por no en cualquier hora en tus configuraciones de perfil." #: bookwyrm/templates/directory/directory.html:31 #: bookwyrm/templates/snippets/goal_card.html:22 @@ -577,20 +541,16 @@ msgid "Dismiss message" msgstr "Desechar mensaje" #: bookwyrm/templates/directory/directory.html:71 -#, fuzzy -#| msgid "followed you" msgid "follower you follow" msgid_plural "followers you follow" -msgstr[0] "te siguió" -msgstr[1] "te siguió" +msgstr[0] "seguidor que tu sigues" +msgstr[1] "seguidores que tu sigues" #: bookwyrm/templates/directory/directory.html:78 -#, fuzzy -#| msgid "Your shelves" msgid "book on your shelves" msgid_plural "books on your shelves" -msgstr[0] "Tus estantes" -msgstr[1] "Tus estantes" +msgstr[0] "libro en tus estantes" +msgstr[1] "libro en tus estantes" #: bookwyrm/templates/directory/directory.html:86 msgid "posts" @@ -605,20 +565,16 @@ msgid "Order by" msgstr "Ordenar por" #: bookwyrm/templates/directory/sort_filter.html:8 -#, fuzzy -#| msgid "Suggest" msgid "Suggested" -msgstr "Sugerir" +msgstr "Sugerido" #: bookwyrm/templates/directory/sort_filter.html:9 msgid "Recently active" msgstr "Activ@ recientemente" #: bookwyrm/templates/directory/user_type_filter.html:5 -#, fuzzy -#| msgid "User Activity" msgid "User type" -msgstr "Actividad de usuario" +msgstr "Tipo de usuario" #: bookwyrm/templates/directory/user_type_filter.html:8 msgid "BookWyrm users" @@ -699,10 +655,8 @@ msgid "Your Account" msgstr "Tu cuenta" #: bookwyrm/templates/edit_author.html:5 -#, fuzzy -#| msgid "Edit Author" msgid "Edit Author:" -msgstr "Editar Autor/Autora" +msgstr "Editar Autor/Autora/Autore:" #: bookwyrm/templates/edit_author.html:32 bookwyrm/templates/lists/form.html:8 #: bookwyrm/templates/user/create_shelf_form.html:13 @@ -754,10 +708,8 @@ msgstr "Preferencia de correo electrónico" #: bookwyrm/templates/email/invite/html_content.html:6 #: bookwyrm/templates/email/invite/subject.html:2 -#, fuzzy, python-format -#| msgid "About %(site_name)s" msgid "You're invited to join %(site_name)s!" -msgstr "Sobre %(site_name)s" +msgstr "¡Estás invitado a unirse con %(site_name)s!" #: bookwyrm/templates/email/invite/html_content.html:9 msgid "Join Now" @@ -774,10 +726,8 @@ msgid "You're invited to join %(site_name)s! Click the link below to create an a msgstr "Estás invitado a unirte con %(site_name)s! Haz clic en el enlace a continuación para crear una cuenta." #: bookwyrm/templates/email/invite/text_content.html:8 -#, fuzzy -#| msgid "More about this site" msgid "Learn more about this instance:" -msgstr "Más sobre este sitio" +msgstr "Aprende más sobre esta intancia:" #: bookwyrm/templates/email/password_reset/html_content.html:6 #: bookwyrm/templates/email/password_reset/text_content.html:4 @@ -799,10 +749,8 @@ msgid "If you didn't request to reset your password, you can ignore this email." msgstr "Si no solicitaste reestablecer tu contraseña, puedes ignorar este mensaje." #: bookwyrm/templates/email/password_reset/subject.html:2 -#, fuzzy, python-format -#| msgid "About %(site_name)s" msgid "Reset your %(site_name)s password" -msgstr "Sobre %(site_name)s" +msgstr "Reestablece tu contraseña de %(site_name)s" #: bookwyrm/templates/feed/direct_messages.html:8 #, python-format @@ -911,16 +859,12 @@ msgstr[0] "%(shared_books)s libro en tus estantes" msgstr[1] "%(shared_books)s libros en tus estantes" #: bookwyrm/templates/get_started/book_preview.html:6 -#, fuzzy, python-format -#| msgid "Want to Read \"%(book_title)s\"" msgid "Have you read %(book_title)s?" -msgstr "Quiero leer \"%(book_title)s\"" +msgstr "¿Has leído %(book_title)s?" #: bookwyrm/templates/get_started/books.html:6 -#, fuzzy -#| msgid "Started reading" msgid "What are you reading?" -msgstr "Lectura se empezó" +msgstr "¿Qué estás leyendo?" #: bookwyrm/templates/get_started/books.html:9 #: bookwyrm/templates/lists/list.html:124 @@ -949,16 +893,12 @@ msgid "Search" msgstr "Buscar" #: bookwyrm/templates/get_started/books.html:26 -#, fuzzy -#| msgid "Suggest Books" msgid "Suggested Books" -msgstr "Sugerir libros" +msgstr "Libros sugeridos" #: bookwyrm/templates/get_started/books.html:41 -#, fuzzy, python-format -#| msgid "About %(site_name)s" msgid "Popular on %(site_name)s" -msgstr "Sobre %(site_name)s" +msgstr "Popular en %(site_name)s" #: bookwyrm/templates/get_started/books.html:51 #: bookwyrm/templates/lists/list.html:141 @@ -971,10 +911,8 @@ msgid "Save & continue" msgstr "Guardar & continuar" #: bookwyrm/templates/get_started/layout.html:14 -#, fuzzy, python-format -#| msgid "About %(site_name)s" msgid "Welcome to %(site_name)s!" -msgstr "Sobre %(site_name)s" +msgstr "¡Bienvenido a %(site_name)s!" #: bookwyrm/templates/get_started/layout.html:16 msgid "These are some first steps to get you started." @@ -982,32 +920,24 @@ msgstr "Estos son unos primeros pasos para empezar." #: bookwyrm/templates/get_started/layout.html:30 #: bookwyrm/templates/get_started/profile.html:6 -#, fuzzy -#| msgid "User Profile" msgid "Create your profile" -msgstr "Perfil de usuario" +msgstr "Crear tu perfil" #: bookwyrm/templates/get_started/layout.html:34 -#, fuzzy -#| msgid "Add Books" msgid "Add books" msgstr "Agregar libros" #: bookwyrm/templates/get_started/layout.html:38 -#, fuzzy -#| msgid "Friendly" msgid "Find friends" -msgstr "Amigable" +msgstr "Encontrar amigos" #: bookwyrm/templates/get_started/layout.html:44 msgid "Skip this step" msgstr "Saltar este paso" #: bookwyrm/templates/get_started/layout.html:48 -#, fuzzy -#| msgid "Finished" msgid "Finish" -msgstr "Terminado" +msgstr "Terminar" #: bookwyrm/templates/get_started/profile.html:15 #: bookwyrm/templates/preferences/edit_user.html:24 @@ -1043,10 +973,8 @@ msgid "Your account will show up in the directory, and may be recommended to oth msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm." #: bookwyrm/templates/get_started/users.html:11 -#, fuzzy -#| msgid "Search for a book or user" msgid "Search for a user" -msgstr "Buscar un libro o un usuario" +msgstr "Buscar un usuario" #: bookwyrm/templates/get_started/users.html:13 #: bookwyrm/templates/search_results.html:76 @@ -1090,10 +1018,8 @@ msgid "Import Books" msgstr "Importar libros" #: bookwyrm/templates/import.html:16 -#, fuzzy -#| msgid "Data source" msgid "Data source:" -msgstr "Fuente de datos" +msgstr "Fuente de datos:" #: bookwyrm/templates/import.html:29 msgid "Data file:" @@ -1146,7 +1072,7 @@ msgstr "(¡Refresca para actualizar!)" #: bookwyrm/templates/import_status.html:35 msgid "Failed to load" -msgstr "Se falló a cargar" +msgstr "No se pudo cargar" #: bookwyrm/templates/import_status.html:44 #, python-format @@ -1298,16 +1224,12 @@ msgid "Create List" msgstr "Crear lista" #: bookwyrm/templates/lists/created_text.html:5 -#, fuzzy, python-format -#| msgid "Added by %(username)s" msgid "Created and curated by %(username)s" -msgstr "Agregado por %(username)s" +msgstr "Agregado y comisariado por %(username)s" #: bookwyrm/templates/lists/created_text.html:7 -#, fuzzy, python-format -#| msgid "Added by %(username)s" msgid "Created by %(username)s" -msgstr "Agregado por %(username)s" +msgstr "Creado por %(username)s" #: bookwyrm/templates/lists/curate.html:6 msgid "Pending Books" @@ -1401,10 +1323,8 @@ msgid "Sort List" msgstr "Ordena la lista" #: bookwyrm/templates/lists/list.html:109 -#, fuzzy -#| msgid "List curation:" msgid "Direction" -msgstr "Enumerar lista de comisariado:" +msgstr "Dirección" #: bookwyrm/templates/lists/list.html:120 msgid "Add Books" @@ -1464,16 +1384,12 @@ msgid "Back to reports" msgstr "Volver a los informes" #: bookwyrm/templates/moderation/report.html:18 -#, fuzzy -#| msgid "Notifications" msgid "Actions" -msgstr "Notificaciones" +msgstr "Acciones" #: bookwyrm/templates/moderation/report.html:19 -#, fuzzy -#| msgid "User Profile" msgid "View user profile" -msgstr "Perfil de usuario" +msgstr "Ver perfil de usuario" #: bookwyrm/templates/moderation/report.html:22 #: bookwyrm/templates/snippets/status/status_options.html:35 @@ -1500,10 +1416,8 @@ msgid "Comment" msgstr "Comentario" #: bookwyrm/templates/moderation/report.html:59 -#, fuzzy -#| msgid "Delete status" msgid "Reported statuses" -msgstr "Eliminar status" +msgstr "Statuses reportados" #: bookwyrm/templates/moderation/report.html:61 msgid "No statuses reported" @@ -1514,10 +1428,8 @@ msgid "Status has been deleted" msgstr "Status ha sido eliminado" #: bookwyrm/templates/moderation/report_modal.html:6 -#, fuzzy, python-format -#| msgid "Lists: %(username)s" msgid "Report @%(username)s" -msgstr "Listas: %(username)s" +msgstr "Reportar @%(username)s" #: bookwyrm/templates/moderation/report_modal.html:21 #, python-format @@ -1525,20 +1437,16 @@ msgid "This report will be sent to %(site_name)s's moderators for review." msgstr "Este informe se enviará a los moderadores de %(site_name)s para la revisión." #: bookwyrm/templates/moderation/report_modal.html:22 -#, fuzzy -#| msgid "More about this site" msgid "More info about this report:" -msgstr "Más sobre este sitio" +msgstr "Más información sobre este informe:" #: bookwyrm/templates/moderation/report_preview.html:13 msgid "No notes provided" msgstr "No se proporcionó notas" #: bookwyrm/templates/moderation/report_preview.html:20 -#, fuzzy, python-format -#| msgid "Added by %(username)s" msgid "Reported by %(username)s" -msgstr "Agregado por %(username)s" +msgstr "Reportado por %(username)s" #: bookwyrm/templates/moderation/report_preview.html:30 msgid "Re-open" @@ -1549,36 +1457,26 @@ msgid "Resolve" msgstr "Resolver" #: bookwyrm/templates/moderation/reports.html:6 -#, fuzzy, python-format -#| msgid "Lists: %(username)s" msgid "Reports: %(server_name)s" -msgstr "Listas: %(username)s" +msgstr "Informes: %(server_name)s" #: bookwyrm/templates/moderation/reports.html:8 #: bookwyrm/templates/moderation/reports.html:16 #: bookwyrm/templates/settings/admin_layout.html:28 -#, fuzzy -#| msgid "Recent Imports" msgid "Reports" -msgstr "Importaciones recientes" +msgstr "Informes" #: bookwyrm/templates/moderation/reports.html:13 -#, fuzzy, python-format -#| msgid "Lists: %(username)s" msgid "Reports: %(server_name)s" -msgstr "Listas: %(username)s" +msgstr "Informes: %(server_name)s" #: bookwyrm/templates/moderation/reports.html:27 -#, fuzzy -#| msgid "Shelved" msgid "Resolved" -msgstr "Archivado" +msgstr "Resuelto" #: bookwyrm/templates/moderation/reports.html:34 -#, fuzzy -#| msgid "No books found" msgid "No reports found." -msgstr "No se encontró ningún libro" +msgstr "No se encontró ningún informe." #: bookwyrm/templates/notifications.html:14 msgid "Delete notifications" @@ -1840,22 +1738,16 @@ msgid "Details" msgstr "Detalles" #: bookwyrm/templates/settings/federated_server.html:15 -#, fuzzy -#| msgid "Software" msgid "Software:" -msgstr "Software" +msgstr "Software:" #: bookwyrm/templates/settings/federated_server.html:19 -#, fuzzy -#| msgid "Description:" msgid "Version:" -msgstr "Descripción:" +msgstr "Versión:" #: bookwyrm/templates/settings/federated_server.html:23 -#, fuzzy -#| msgid "Status" msgid "Status:" -msgstr "Status" +msgstr "Status:" #: bookwyrm/templates/settings/federated_server.html:30 #: bookwyrm/templates/user/user_layout.html:50 @@ -1863,10 +1755,8 @@ msgid "Activity" msgstr "Actividad" #: bookwyrm/templates/settings/federated_server.html:33 -#, fuzzy -#| msgid "Username:" msgid "Users:" -msgstr "Nombre de usuario:" +msgstr "Usuarios:" #: bookwyrm/templates/settings/federated_server.html:36 #: bookwyrm/templates/settings/federated_server.html:43 @@ -1874,38 +1764,28 @@ msgid "View all" msgstr "Ver todos" #: bookwyrm/templates/settings/federated_server.html:40 -#, fuzzy -#| msgid "Recent Imports" msgid "Reports:" -msgstr "Importaciones recientes" +msgstr "Informes:" #: bookwyrm/templates/settings/federated_server.html:47 -#, fuzzy -#| msgid "followed you" msgid "Followed by us:" -msgstr "te siguió" +msgstr "Seguido por nosotros:" #: bookwyrm/templates/settings/federated_server.html:53 -#, fuzzy -#| msgid "followed you" msgid "Followed by them:" -msgstr "te siguió" +msgstr "Seguido por ellos:" #: bookwyrm/templates/settings/federated_server.html:59 -#, fuzzy -#| msgid "Blocked Users" msgid "Blocked by us:" -msgstr "Usuarios bloqueados" +msgstr "Bloqueado por nosotros:" #: bookwyrm/templates/settings/federation.html:13 msgid "Server name" msgstr "Nombre de servidor" #: bookwyrm/templates/settings/federation.html:17 -#, fuzzy -#| msgid "Federated" msgid "Date federated" -msgstr "Federalizado" +msgstr "Fecha de federalización" #: bookwyrm/templates/settings/federation.html:21 msgid "Software" @@ -1922,42 +1802,32 @@ msgstr "Status" #: bookwyrm/templates/settings/manage_invite_requests.html:11 #: bookwyrm/templates/settings/manage_invite_requests.html:25 #: bookwyrm/templates/settings/manage_invites.html:11 -#, fuzzy -#| msgid "Invites" msgid "Invite Requests" -msgstr "Invitaciones" +msgstr "Solicitudes de invitación" #: bookwyrm/templates/settings/manage_invite_requests.html:23 msgid "Ignored Invite Requests" msgstr "Solicitudes de invitación ignoradas" #: bookwyrm/templates/settings/manage_invite_requests.html:35 -#, fuzzy -#| msgid "Federated" msgid "Date requested" -msgstr "Federalizado" +msgstr "Fecha solicitada" #: bookwyrm/templates/settings/manage_invite_requests.html:39 -#, fuzzy -#| msgid "Accept" msgid "Date accepted" -msgstr "Aceptar" +msgstr "Fecha de aceptación" #: bookwyrm/templates/settings/manage_invite_requests.html:42 msgid "Email" msgstr "Correo electronico" #: bookwyrm/templates/settings/manage_invite_requests.html:47 -#, fuzzy -#| msgid "Notifications" msgid "Action" -msgstr "Notificaciones" +msgstr "Acción" #: bookwyrm/templates/settings/manage_invite_requests.html:50 -#, fuzzy -#| msgid "Follow Requests" msgid "No requests" -msgstr "Solicitudes de seguidor" +msgstr "No solicitudes" #: bookwyrm/templates/settings/manage_invite_requests.html:59 #: bookwyrm/templates/settings/status_filter.html:16 @@ -2083,10 +1953,8 @@ msgid "Allow registration:" msgstr "Permitir registración:" #: bookwyrm/templates/settings/site.html:83 -#, fuzzy -#| msgid "Follow Requests" msgid "Allow invite requests:" -msgstr "Solicitudes de seguidor" +msgstr "Permitir solicitudes de invitación:" #: bookwyrm/templates/settings/site.html:87 msgid "Registration closed text:" @@ -2098,32 +1966,24 @@ msgid "Users: %(server_name)s" msgstr "Usuarios %(server_name)s" #: bookwyrm/templates/settings/user_admin.html:20 -#, fuzzy -#| msgid "Username:" msgid "Username" -msgstr "Nombre de usuario:" +msgstr "Nombre de usuario" #: bookwyrm/templates/settings/user_admin.html:24 -#, fuzzy -#| msgid "Added:" msgid "Date Added" -msgstr "Agregado:" +msgstr "Fecha agregada" #: bookwyrm/templates/settings/user_admin.html:28 msgid "Last Active" msgstr "Actividad reciente" #: bookwyrm/templates/settings/user_admin.html:36 -#, fuzzy -#| msgid "Remove" msgid "Remote server" -msgstr "Quitar" +msgstr "Quitar servidor" #: bookwyrm/templates/settings/user_admin.html:45 -#, fuzzy -#| msgid "Activity" msgid "Active" -msgstr "Actividad" +msgstr "Activ@" #: bookwyrm/templates/settings/user_admin.html:45 msgid "Inactive" @@ -2175,22 +2035,16 @@ msgid "Quote" msgstr "Cita" #: bookwyrm/templates/snippets/create_status_form.html:18 -#, fuzzy -#| msgid "Comment" msgid "Comment:" -msgstr "Comentario" +msgstr "Comentario:" #: bookwyrm/templates/snippets/create_status_form.html:20 -#, fuzzy -#| msgid "Quote" msgid "Quote:" -msgstr "Cita" +msgstr "Cita:" #: bookwyrm/templates/snippets/create_status_form.html:22 -#, fuzzy -#| msgid "Review" msgid "Review:" -msgstr "Reseña" +msgstr "Reseña:" #: bookwyrm/templates/snippets/create_status_form.html:56 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 @@ -2258,10 +2112,8 @@ msgid "Un-like status" msgstr "Quitar me gusta de status" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:7 -#, fuzzy -#| msgid "Show less" msgid "Show filters" -msgstr "Mostrar menos" +msgstr "Mostrar filtros" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:9 msgid "Hide filters" @@ -2272,20 +2124,16 @@ msgid "Apply filters" msgstr "Aplicar filtros" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:26 -#, fuzzy -#| msgid "Clear search" msgid "Clear filters" -msgstr "Borrar búsqueda" +msgstr "Borrar filtros" #: bookwyrm/templates/snippets/follow_button.html:12 msgid "Follow" msgstr "Seguir" #: bookwyrm/templates/snippets/follow_button.html:18 -#, fuzzy -#| msgid "Send follow request" msgid "Undo follow request" -msgstr "Envia solicitud de seguidor" +msgstr "Des-enviar solicitud de seguidor" #: bookwyrm/templates/snippets/follow_button.html:20 msgid "Unfollow" @@ -2316,12 +2164,10 @@ msgstr[0] "estableció una meta de leer %(counter)s libro en %(year)s" msgstr[1] "estableció una meta de leer %(counter)s libros en %(year)s" #: bookwyrm/templates/snippets/generated_status/rating.html:3 -#, fuzzy, python-format -#| msgid "%(title)s by " msgid "Rated %(title)s: %(display_rating)s star" msgid_plural "Rated %(title)s: %(display_rating)s stars" -msgstr[0] "%(title)s por " -msgstr[1] "%(title)s por " +msgstr[0] "Reseño %(title)s: %(display_rating)s estrella" +msgstr[1] "Reseño %(title)s: %(display_rating)s estrellas" #: bookwyrm/templates/snippets/generated_status/review_pure_name.html:4 #, python-format @@ -2383,16 +2229,12 @@ msgid "%(username)s has read %(read_count)s of %(goal_count msgstr "%(username)s ha leído %(read_count)s de %(goal_count)s libros." #: bookwyrm/templates/snippets/page_text.html:4 -#, fuzzy, python-format -#| msgid "of %(pages)s pages" msgid "page %(page)s of %(total_pages)s" -msgstr "de %(pages)s páginas" +msgstr "página %(page)s de %(total_pages)s" #: bookwyrm/templates/snippets/page_text.html:6 -#, fuzzy, python-format -#| msgid "%(pages)s pages" msgid "page %(page)s" -msgstr "%(pages)s páginas" +msgstr "página %(pages)s" #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 @@ -2476,10 +2318,8 @@ msgid "Sign Up" msgstr "Inscribirse" #: bookwyrm/templates/snippets/report_button.html:5 -#, fuzzy -#| msgid "Import" msgid "Report" -msgstr "Importar" +msgstr "Reportar" #: bookwyrm/templates/snippets/rss_title.html:5 #: bookwyrm/templates/snippets/status/status_header.html:11 @@ -2502,10 +2342,8 @@ msgid "quoted" msgstr "citó" #: bookwyrm/templates/snippets/search_result_text.html:10 -#, fuzzy -#| msgid "Add cover" msgid "No cover" -msgstr "Agregar portada" +msgstr "Sin portada" #: bookwyrm/templates/snippets/search_result_text.html:22 #, python-format @@ -2517,10 +2355,8 @@ msgid "Import book" msgstr "Importar libro" #: bookwyrm/templates/snippets/shelf_selector.html:4 -#, fuzzy -#| msgid "Your books" msgid "Move book" -msgstr "Tus libros" +msgstr "Mover libro" #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 #, python-format @@ -2529,10 +2365,8 @@ msgstr "Terminar \"%(book_title)s\"" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:35 -#, fuzzy -#| msgid "Updates" msgid "Update progress" -msgstr "Actualizaciones" +msgstr "Progreso de actualización" #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" @@ -2552,10 +2386,8 @@ msgid "Want to read" msgstr "Quiero leer" #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 -#, fuzzy, python-format -#| msgid "Lists: %(username)s" msgid "Remove from %(name)s" -msgstr "Listas: %(username)s" +msgstr "Quitar de %(name)s" #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 #, python-format @@ -2597,28 +2429,20 @@ msgid "Open image in new window" msgstr "Abrir imagen en una nueva ventana" #: bookwyrm/templates/snippets/status/status_header.html:22 -#, fuzzy, python-format -#| msgid "Added by %(username)s" msgid "replied to %(username)s's review" -msgstr "Agregado por %(username)s" +msgstr "respondió a la reseña de %(username)s " #: bookwyrm/templates/snippets/status/status_header.html:24 -#, fuzzy, python-format -#| msgid "replied to your status" msgid "replied to %(username)s's comment" -msgstr "respondió a tu status" +msgstr "respondió al comentario de %(username)s " #: bookwyrm/templates/snippets/status/status_header.html:26 -#, fuzzy, python-format -#| msgid "replied to your status" msgid "replied to %(username)s's quote" -msgstr "respondió a tu status" +msgstr "respondió a la cita de %(username)s " #: bookwyrm/templates/snippets/status/status_header.html:28 -#, fuzzy, python-format -#| msgid "replied to your status" msgid "replied to %(username)s's status" -msgstr "respondió a tu status" +msgstr "respondió al status de %(username)s " #: bookwyrm/templates/snippets/status/status_options.html:7 #: bookwyrm/templates/snippets/user_options.html:7 @@ -2626,26 +2450,20 @@ msgid "More options" msgstr "Más opciones" #: bookwyrm/templates/snippets/status/status_options.html:27 -#, fuzzy -#| msgid "Delete these read dates" msgid "Delete & re-draft" -msgstr "Eliminar estas fechas de lectura" +msgstr "Eliminar y recomponer" #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "Cambiar a esta edición" #: bookwyrm/templates/snippets/table-sort-header.html:6 -#, fuzzy -#| msgid "Started reading" msgid "Sorted ascending" -msgstr "Lectura se empezó" +msgstr "En orden ascendente" #: bookwyrm/templates/snippets/table-sort-header.html:10 -#, fuzzy -#| msgid "Started reading" msgid "Sorted descending" -msgstr "Lectura se empezó" +msgstr "En orden descendente" #: bookwyrm/templates/snippets/tag.html:14 msgid "Remove tag" @@ -2661,10 +2479,8 @@ msgid "Books tagged \"%(tag.name)s\"" msgstr "Libros etiquetados con \"%(tag.name)s\"" #: bookwyrm/templates/user/books_header.html:5 -#, fuzzy, python-format -#| msgid "%(username)s's %(year)s Books" msgid "%(username)s's books" -msgstr "Los libros de %(username)s para %(year)s" +msgstr "Los libros de %(username)s" #: bookwyrm/templates/user/create_shelf_form.html:5 #: bookwyrm/templates/user/create_shelf_form.html:22 @@ -2709,10 +2525,8 @@ msgid "Create list" msgstr "Crear lista" #: bookwyrm/templates/user/shelf.html:24 bookwyrm/views/shelf.py:56 -#, fuzzy -#| msgid "books" msgid "All books" -msgstr "libros" +msgstr "Todos los libros" #: bookwyrm/templates/user/shelf.html:37 msgid "Create shelf" @@ -2747,10 +2561,8 @@ msgid "Edit profile" msgstr "Editar perfil" #: bookwyrm/templates/user/user.html:34 -#, fuzzy, python-format -#| msgid "See all %(size)s" msgid "View all %(size)s" -msgstr "Ver %(size)s" +msgstr "Ver todos los %(size)s" #: bookwyrm/templates/user/user.html:47 msgid "View all books" @@ -2782,10 +2594,8 @@ msgid "Reading Goal" msgstr "Meta de lectura" #: bookwyrm/templates/user/user_layout.html:68 -#, fuzzy -#| msgid "Book" msgid "Books" -msgstr "Libro" +msgstr "Libros" #: bookwyrm/templates/user/user_preview.html:13 #, python-format @@ -2805,10 +2615,8 @@ msgid "%(counter)s following" msgstr "%(counter)s siguiendo" #: bookwyrm/views/password.py:32 -#, fuzzy -#| msgid "A user with that username already exists." msgid "No user with that email address was found." -msgstr "Ya existe un usuario con ese nombre." +msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónico." #: bookwyrm/views/password.py:41 #, python-format @@ -2821,10 +2629,8 @@ msgid "ambiguous option: %(option)s could match %(matches)s" msgstr "opción ambiguo: %(option)s pudiera coincidir con %(matches)s" #: venv/lib/python3.8/site-packages/django/contrib/messages/apps.py:7 -#, fuzzy -#| msgid "All messages" msgid "Messages" -msgstr "Todos los mensajes" +msgstr "Mensajes" #: venv/lib/python3.8/site-packages/django/contrib/sitemaps/apps.py:7 msgid "Site Maps" @@ -2851,29 +2657,21 @@ msgid "That page contains no results" msgstr "Esa pagina no contiene resultados" #: venv/lib/python3.8/site-packages/django/core/validators.py:20 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid value." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese un valor válido." #: venv/lib/python3.8/site-packages/django/core/validators.py:91 #: venv/lib/python3.8/site-packages/django/forms/fields.py:671 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid URL." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una URL válida." #: venv/lib/python3.8/site-packages/django/core/validators.py:145 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid integer." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese un entero válido." #: venv/lib/python3.8/site-packages/django/core/validators.py:156 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid email address." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una dirección de correo electrónico válida." #. Translators: "letters" means latin letters: a-z and A-Z. #: venv/lib/python3.8/site-packages/django/core/validators.py:230 @@ -2886,24 +2684,18 @@ msgstr "Ingrese un “slug” válido que consiste de letras Unicode, numeros, g #: venv/lib/python3.8/site-packages/django/core/validators.py:246 #: venv/lib/python3.8/site-packages/django/core/validators.py:266 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid IPv4 address." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una dirección IPv4 válida." #: venv/lib/python3.8/site-packages/django/core/validators.py:251 #: venv/lib/python3.8/site-packages/django/core/validators.py:267 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid IPv6 address." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una dirección IPv6 válida." #: venv/lib/python3.8/site-packages/django/core/validators.py:261 #: venv/lib/python3.8/site-packages/django/core/validators.py:265 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una dirección IPv4 o IPv6 válida." #: venv/lib/python3.8/site-packages/django/core/validators.py:295 msgid "Enter only digits separated by commas." @@ -2941,10 +2733,8 @@ msgstr[1] "Verifica que este valor tiene a lo sumo %(limit_value)d caracteres. ( #: venv/lib/python3.8/site-packages/django/core/validators.py:387 #: venv/lib/python3.8/site-packages/django/forms/fields.py:292 #: venv/lib/python3.8/site-packages/django/forms/fields.py:327 -#, fuzzy -#| msgid "Series number:" msgid "Enter a number." -msgstr "Número de serie:" +msgstr "Ingrese un número." #: venv/lib/python3.8/site-packages/django/core/validators.py:389 #, python-format @@ -2983,32 +2773,24 @@ msgid "and" msgstr "y" #: venv/lib/python3.8/site-packages/django/db/models/base.py:1192 -#, fuzzy, python-format -#| msgid "A user with that username already exists." msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "Ya existe un usuario con ese nombre." +msgstr "Ya existe %(model_name)s con este %(field_labels)s." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:100 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid remote_id" msgid "Value %(value)r is not a valid choice." -msgstr "%(value)s no es un remote_id válido" +msgstr "El valor %(value)s no es una opción válida." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:101 -#, fuzzy -#| msgid "This shelf is empty." msgid "This field cannot be null." -msgstr "Este estante está vacio." +msgstr "Este campo no puede ser nulo." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:102 msgid "This field cannot be blank." msgstr "Este campo no puede ser vacio." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:103 -#, fuzzy, python-format -#| msgid "A user with that username already exists." msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "Ya existe un usuario con ese nombre." +msgstr "Ya existe %(model_name)s con este %(field_labels)s." #. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. #. Eg: "Title must be unique for pub_date year" @@ -3042,10 +2824,8 @@ msgid "String (up to %(max_length)s)" msgstr "Cadena (máximo de %(max_length)s caracteres)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1047 -#, fuzzy -#| msgid "No active invites" msgid "Comma-separated integers" -msgstr "No invitaciónes activas" +msgstr "Enteros separados por comas" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1096 #, python-format @@ -3077,16 +2857,12 @@ msgid "Date (with time)" msgstr "Fecha (con la hora)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1395 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid username" msgid "“%(value)s” value must be a decimal number." -msgstr "%(value)s no es un usuario válido" +msgstr "El valor de “%(value)s” debe ser un número decimal." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1397 -#, fuzzy -#| msgid "Series number:" msgid "Decimal number" -msgstr "Número de serie:" +msgstr "Número decimal" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1536 #, python-format @@ -3094,24 +2870,18 @@ msgid "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM: msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato [DD] [[HH:]MM:]ss[.uuuuuu]." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1539 -#, fuzzy -#| msgid "List curation:" msgid "Duration" -msgstr "Enumerar lista de comisariado:" +msgstr "Duración" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1589 -#, fuzzy -#| msgid "Email address:" msgid "Email address" -msgstr "Dirección de correo electrónico:" +msgstr "Dirección de correo electrónico" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1612 msgid "File path" msgstr "Ruta de archivo" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1678 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid username" msgid "“%(value)s” value must be a float." msgstr "%(value)s no es un usuario válido" @@ -3129,22 +2899,16 @@ msgid "Integer" msgstr "Entero" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1803 -#, fuzzy -#| msgid "No active invites" msgid "Big (8 byte) integer" -msgstr "No invitaciónes activas" +msgstr "Entero grande (8 byte)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1819 -#, fuzzy -#| msgid "Email address:" msgid "IPv4 address" -msgstr "Dirección de correo electrónico:" +msgstr "Dirección IPv4" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1850 -#, fuzzy -#| msgid "Email address:" msgid "IP address" -msgstr "Dirección de correo electrónico:" +msgstr "Dirección IP" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1930 #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1931 @@ -3157,22 +2921,16 @@ msgid "Boolean (Either True, False or None)" msgstr "Booleano (O True, Falso, o None)" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1976 -#, fuzzy -#| msgid "No active invites" msgid "Positive big integer" -msgstr "No invitaciónes activas" +msgstr "Entero positivo grande" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1989 -#, fuzzy -#| msgid "No active invites" msgid "Positive integer" -msgstr "No invitaciónes activas" +msgstr "Entero positivo" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2002 -#, fuzzy -#| msgid "No active invites" msgid "Positive small integer" -msgstr "No invitaciónes activas" +msgstr "Entero positivo pequeño " #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2016 #, python-format @@ -3210,10 +2968,8 @@ msgid "Raw binary data" msgstr "Datos binarios sin procesar" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2301 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid username" msgid "“%(value)s” is not a valid UUID." -msgstr "%(value)s no es un usuario válido" +msgstr "%(value)s no es una UUID válida." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2303 msgid "Universally unique identifier" @@ -3224,10 +2980,8 @@ msgid "File" msgstr "Archivo" #: venv/lib/python3.8/site-packages/django/db/models/fields/files.py:379 -#, fuzzy -#| msgid "Images" msgid "Image" -msgstr "Imagenes" +msgstr "Imágen" #: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:18 msgid "A JSON object" @@ -3235,7 +2989,7 @@ msgstr "Un objeto JSON" #: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:20 msgid "Value must be valid JSON." -msgstr "Valor debe ser JSON valido." +msgstr "Valor debe ser JSON válido." #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:790 #, python-format @@ -3247,28 +3001,20 @@ msgid "Foreign Key (type determined by related field)" msgstr "Clave externa (tipo determinado por campo relacionado)" #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1045 -#, fuzzy -#| msgid "Relationships" msgid "One-to-one relationship" -msgstr "Relaciones" +msgstr "Relación uno-a-uno" #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1099 -#, fuzzy, python-format -#| msgid "Relationships" msgid "%(from)s-%(to)s relationship" -msgstr "Relaciones" +msgstr "relación %(from)s-%(to)s" #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1100 -#, fuzzy, python-format -#| msgid "Relationships" msgid "%(from)s-%(to)s relationships" -msgstr "Relaciones" +msgstr "relaciones %(from)s-%(to)s" #: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1142 -#, fuzzy -#| msgid "Relationships" msgid "Many-to-many relationship" -msgstr "Relaciones" +msgstr "Relaciones mucho-a-mucho" #. Translators: If found as last label character, these punctuation #. characters will prevent the default label_suffix to be appended to the label @@ -3277,42 +3023,30 @@ msgid ":?.!" msgstr "" #: venv/lib/python3.8/site-packages/django/forms/fields.py:54 -#, fuzzy -#| msgid "This shelf is empty." msgid "This field is required." -msgstr "Este estante está vacio." +msgstr "Este campo es requerido." #: venv/lib/python3.8/site-packages/django/forms/fields.py:247 -#, fuzzy -#| msgid "Series number:" msgid "Enter a whole number." -msgstr "Número de serie:" +msgstr "Ingrese un número entero." #: venv/lib/python3.8/site-packages/django/forms/fields.py:398 #: venv/lib/python3.8/site-packages/django/forms/fields.py:1139 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid date." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una fecha válida." #: venv/lib/python3.8/site-packages/django/forms/fields.py:422 #: venv/lib/python3.8/site-packages/django/forms/fields.py:1140 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid time." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una hora válida." #: venv/lib/python3.8/site-packages/django/forms/fields.py:450 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid date/time." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una fecha/hora válida." #: venv/lib/python3.8/site-packages/django/forms/fields.py:484 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid duration." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una duración válida." #: venv/lib/python3.8/site-packages/django/forms/fields.py:485 #, python-brace-format @@ -3328,10 +3062,8 @@ msgid "No file was submitted." msgstr "No se aceptó ningun archivo." #: venv/lib/python3.8/site-packages/django/forms/fields.py:547 -#, fuzzy -#| msgid "This shelf is empty." msgid "The submitted file is empty." -msgstr "Este estante está vacio." +msgstr "El archivo enviado está vacio." #: venv/lib/python3.8/site-packages/django/forms/fields.py:549 #, python-format @@ -3346,38 +3078,32 @@ msgstr "Por favor, o envia un archivo o marca la casilla vacia, no los dos." #: venv/lib/python3.8/site-packages/django/forms/fields.py:613 msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." -msgstr "Subir una imagen valida. El archivo que subiste o no fue imagen o fue corrupto." +msgstr "Subir una imagen válida. El archivo que subiste o no fue imagen o fue corrupto." #: venv/lib/python3.8/site-packages/django/forms/fields.py:775 #: venv/lib/python3.8/site-packages/django/forms/fields.py:865 #: venv/lib/python3.8/site-packages/django/forms/models.py:1296 #, python-format msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "Selecciona una opción valida. %(value)s no es una de las opciones disponibles." +msgstr "Selecciona una opción válida. %(value)s no es una de las opciones disponibles." #: venv/lib/python3.8/site-packages/django/forms/fields.py:866 #: venv/lib/python3.8/site-packages/django/forms/fields.py:981 #: venv/lib/python3.8/site-packages/django/forms/models.py:1295 -#, fuzzy -#| msgid "Email address:" msgid "Enter a list of values." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una lista de valores." #: venv/lib/python3.8/site-packages/django/forms/fields.py:982 msgid "Enter a complete value." msgstr "Ingresa un valor completo." #: venv/lib/python3.8/site-packages/django/forms/fields.py:1198 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid UUID." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una UUID válida." #: venv/lib/python3.8/site-packages/django/forms/fields.py:1228 -#, fuzzy -#| msgid "Email address:" msgid "Enter a valid JSON." -msgstr "Dirección de correo electrónico:" +msgstr "Ingrese una JSON válida." #. Translators: This is the default suffix added to form field labels #: venv/lib/python3.8/site-packages/django/forms/forms.py:78 @@ -3443,10 +3169,8 @@ msgid "Select a valid choice. That choice is not one of the available choices." msgstr "Selecciona una opción válida. Esa opción no es una de las opciones disponibles." #: venv/lib/python3.8/site-packages/django/forms/models.py:1298 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid username" msgid "“%(pk)s” is not a valid value." -msgstr "%(value)s no es un usuario válido" +msgstr "“%(pk)s” no es un valor válido." #: venv/lib/python3.8/site-packages/django/forms/utils.py:167 #, python-format @@ -3458,16 +3182,12 @@ msgid "Clear" msgstr "Borrar" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:399 -#, fuzzy -#| msgid "Currently Reading" msgid "Currently" -msgstr "Leyendo actualmente" +msgstr "Actualmente" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:400 -#, fuzzy -#| msgid "Change shelf" msgid "Change" -msgstr "Cambiar estante" +msgstr "Cambiar" #: venv/lib/python3.8/site-packages/django/forms/widgets.py:709 msgid "Unknown" @@ -3836,7 +3556,7 @@ msgstr "Diciembre" #: venv/lib/python3.8/site-packages/django/utils/ipv6.py:8 msgid "This is not a valid IPv6 address." -msgstr "Esta no es una valida dirección IPv6." +msgstr "Esta no es una dirección IPv6 válida." #: venv/lib/python3.8/site-packages/django/utils/text.py:70 #, python-format @@ -3967,10 +3687,8 @@ msgid "Invalid date string “%(datestr)s” given format “%(format)s”" msgstr "Cadena de fecha invalida “%(datestr)s” dado el formato “%(format)s”" #: venv/lib/python3.8/site-packages/django/views/generic/detail.py:54 -#, fuzzy, python-format -#| msgid "No books found matching the query \"%(query)s\"" msgid "No %(verbose_name)s found matching the query" -msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query)s\"" +msgstr "No se encontró ningún %(verbose_name)s correspondiente a la búsqueda" #: venv/lib/python3.8/site-packages/django/views/generic/list.py:67 msgid "Page is not “last”, nor can it be converted to an int." @@ -3991,10 +3709,8 @@ msgid "Directory indexes are not allowed here." msgstr "Indices directorios no se permiten aquí." #: venv/lib/python3.8/site-packages/django/views/static.py:42 -#, fuzzy, python-format -#| msgid "%(value)s is not a valid username" msgid "“%(path)s” does not exist" -msgstr "%(value)s no es un usuario válido" +msgstr "“%(path)s” no existe" #: venv/lib/python3.8/site-packages/django/views/static.py:80 #, python-format @@ -4036,10 +3752,8 @@ msgid "Get started with Django" msgstr "Empezar con Django" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:408 -#, fuzzy -#| msgid "Comment" msgid "Django Community" -msgstr "Comentario" +msgstr "Comunidad Django" #: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:409 msgid "Connect, get help, or contribute" From 9400510b21f8105a04b4b5ac580d6854da4ac27f Mon Sep 17 00:00:00 2001 From: reese Date: Wed, 21 Apr 2021 15:52:44 -0500 Subject: [PATCH 082/109] compile messages, fix typos --- locale/es/LC_MESSAGES/django.mo | Bin 26563 -> 65812 bytes locale/es/LC_MESSAGES/django.po | 6 +++--- locale/fr_FR/LC_MESSAGES/django.mo | Bin 42813 -> 42851 bytes 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index d42d8394517c6921e9ae059a8a9affcf6fac1a68..44788295d68754777a83997a986f032a60cfcc30 100644 GIT binary patch literal 65812 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 K+HenJ-KM_*@;BW8 delta 10665 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 E0rw*bJpcdz diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 2fbf981c0..62b6ac25c 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -1640,7 +1640,7 @@ msgstr "Mostrar meta de lectura en el feed:" #: bookwyrm/templates/preferences/edit_user.html:62 #, python-format msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users." -msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm."" +msgstr "Tu cuenta se aparecerá en el directorio, y puede ser recomendado a otros usuarios de BookWyrm." #: bookwyrm/templates/preferences/edit_user.html:65 msgid "Preferred Timezone: " @@ -2914,7 +2914,7 @@ msgstr "Dirección IP" #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1931 #, python-format msgid "“%(value)s” value must be either None, True or False." -msgstr "Valor debe ser o None, True, o False." +msgstr "Valor “%(value)s” debe ser o None, True, o False." #: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1933 msgid "Boolean (Either True, False or None)" @@ -3139,7 +3139,7 @@ msgstr[1] "Por favor, enviar %d o más formularios." # TODO cc @mouse is this a verb or noun msgid "Order" msgstr "Pedir" # if verb -msgstr "Pedido" # if noun +# msgstr "Pedido" # if noun #: venv/lib/python3.8/site-packages/django/forms/models.py:755 #, python-format diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 09e90f22c801bc681e5dfda3c171b81a4da45afc..b91a542dbfb13e56f1baff5aeab3b9c4a3088116 100644 GIT binary patch delta 12199 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 delta 12183 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 bX6&j_zJ0osWj%}U`Z_kX(ynDaPuBWB*blDr From e4b432246a7c83cb454b32cce3e4554506dc37db Mon Sep 17 00:00:00 2001 From: reese Date: Thu, 22 Apr 2021 11:03:41 -0500 Subject: [PATCH 083/109] replace venv3 with venv, makemessages for es, compilemessages for es --- bw-dev | 4 +- locale/es/LC_MESSAGES/django.mo | Bin 65812 -> 42569 bytes locale/es/LC_MESSAGES/django.po | 2776 ++++++++++++++----------------- 3 files changed, 1265 insertions(+), 1515 deletions(-) diff --git a/bw-dev b/bw-dev index 42fb4a2e7..c2b63bc17 100755 --- a/bw-dev +++ b/bw-dev @@ -90,10 +90,10 @@ case "$CMD" in runweb python manage.py collectstatic --no-input ;; makemessages) - runweb django-admin makemessages --no-wrap --ignore=venv3 $@ + runweb django-admin makemessages --no-wrap --ignore=venv $@ ;; compilemessages) - runweb django-admin compilemessages --ignore venv3 $@ + runweb django-admin compilemessages --ignore venv $@ ;; build) docker-compose build diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index 44788295d68754777a83997a986f032a60cfcc30..f0d87d7039ba2302eba8733872a4fa81b1cb94f5 100644 GIT binary patch delta 14983 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 K+HenJ-KM_*@;BW8 diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 62b6ac25c..a6274f7a1 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-11 01:59+0000\n" +"POT-Creation-Date: 2021-04-22 15:55+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,60 +18,57 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:226 +#: bookwyrm/forms.py:232 msgid "A user with this email already exists." msgstr "Ya existe un usuario con ese correo electrónico." -#: bookwyrm/forms.py:240 +#: bookwyrm/forms.py:246 msgid "One Day" msgstr "Un día" -#: bookwyrm/forms.py:241 +#: bookwyrm/forms.py:247 msgid "One Week" msgstr "Una semana" -#: bookwyrm/forms.py:242 +#: bookwyrm/forms.py:248 msgid "One Month" msgstr "Un mes" -#: bookwyrm/forms.py:243 +#: bookwyrm/forms.py:249 msgid "Does Not Expire" msgstr "Nunca se vence" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:254 #, python-format msgid "%(count)d uses" msgstr "%(count)d usos" -#: bookwyrm/forms.py:251 +#: bookwyrm/forms.py:257 msgid "Unlimited" msgstr "Sin límite" -#: bookwyrm/forms.py:289 +#: bookwyrm/forms.py:301 msgid "List Order" msgstr "Orden de la lista" -#: bookwyrm/forms.py:290 -#| msgid "Title" +#: bookwyrm/forms.py:302 msgid "Book Title" msgstr "Título" -#: bookwyrm/forms.py:291 bookwyrm/templates/snippets/create_status_form.html:29 +#: bookwyrm/forms.py:303 bookwyrm/templates/snippets/create_status_form.html:31 #: bookwyrm/templates/user/shelf.html:81 msgid "Rating" msgstr "Calificación" -#: bookwyrm/forms.py:293 bookwyrm/templates/lists/list.html:105 +#: bookwyrm/forms.py:305 bookwyrm/templates/lists/list.html:72 msgid "Sort By" msgstr "Ordenar por" -#: bookwyrm/forms.py:297 -#| msgid "Started reading" +#: bookwyrm/forms.py:309 msgid "Ascending" msgstr "Ascendente" -#: bookwyrm/forms.py:298 -#| msgid "Started reading" +#: bookwyrm/forms.py:310 msgid "Descending" msgstr "Descendente" @@ -85,7 +82,7 @@ msgstr "%(value)s no es un remote_id válido" msgid "%(value)s is not a valid username" msgstr "%(value)s no es un usuario válido" -#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:152 +#: bookwyrm/models/fields.py:165 bookwyrm/templates/layout.html:153 msgid "username" msgstr "nombre de usuario" @@ -93,23 +90,23 @@ msgstr "nombre de usuario" msgid "A user with that username already exists." msgstr "Ya existe un usuario con ese nombre." -#: bookwyrm/settings.py:150 +#: bookwyrm/settings.py:152 msgid "English" msgstr "Inglés" -#: bookwyrm/settings.py:151 +#: bookwyrm/settings.py:153 msgid "German" msgstr "Aléman" -#: bookwyrm/settings.py:152 +#: bookwyrm/settings.py:154 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:153 +#: bookwyrm/settings.py:155 msgid "French" msgstr "Francés" -#: bookwyrm/settings.py:154 +#: bookwyrm/settings.py:156 msgid "Simplified Chinese" msgstr "Chino simplificado" @@ -146,77 +143,67 @@ msgstr "Wikipedia" msgid "Books by %(name)s" msgstr "Libros de %(name)s" -#: bookwyrm/templates/book/book.html:21 +#: bookwyrm/templates/book/book.html:33 #: bookwyrm/templates/discover/large-book.html:12 #: bookwyrm/templates/discover/small-book.html:9 msgid "by" msgstr "por" -#: bookwyrm/templates/book/book.html:29 bookwyrm/templates/book/book.html:30 +#: bookwyrm/templates/book/book.html:41 bookwyrm/templates/book/book.html:42 msgid "Edit Book" msgstr "Editar Libro" -#: bookwyrm/templates/book/book.html:49 +#: bookwyrm/templates/book/book.html:61 #: bookwyrm/templates/book/cover_modal.html:5 msgid "Add cover" msgstr "Agregar portada" -#: bookwyrm/templates/book/book.html:53 +#: bookwyrm/templates/book/book.html:65 msgid "Failed to load cover" msgstr "No se pudo cargar la portada" -#: bookwyrm/templates/book/book.html:62 -msgid "ISBN:" -msgstr "ISBN:" - -#: bookwyrm/templates/book/book.html:69 -#: bookwyrm/templates/book/edit_book.html:223 -msgid "OCLC Number:" -msgstr "Número OCLC:" - -#: bookwyrm/templates/book/book.html:76 -#: bookwyrm/templates/book/edit_book.html:227 -msgid "ASIN:" -msgstr "ASIN:" - -#: bookwyrm/templates/book/book.html:85 +#: bookwyrm/templates/book/book.html:82 msgid "View on OpenLibrary" msgstr "Ver en OpenLibrary" -#: bookwyrm/templates/book/book.html:94 +#: bookwyrm/templates/book/book.html:102 #, python-format msgid "(%(review_count)s review)" msgid_plural "(%(review_count)s reviews)" msgstr[0] "(%(review_count)s reseña)" msgstr[1] "(%(review_count)s reseñas)" -#: bookwyrm/templates/book/book.html:100 +#: bookwyrm/templates/book/book.html:114 msgid "Add Description" msgstr "Agregar descripción" -#: bookwyrm/templates/book/book.html:107 +#: bookwyrm/templates/book/book.html:121 #: bookwyrm/templates/book/edit_book.html:107 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Descripción:" -#: bookwyrm/templates/book/book.html:111 -#: bookwyrm/templates/book/edit_book.html:237 +#: bookwyrm/templates/book/book.html:125 +#: bookwyrm/templates/book/edit_book.html:240 #: bookwyrm/templates/edit_author.html:78 bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:70 +#: bookwyrm/templates/settings/edit_server.html:68 +#: bookwyrm/templates/settings/federated_server.html:93 #: bookwyrm/templates/settings/site.html:93 #: bookwyrm/templates/snippets/readthrough.html:75 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:34 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:38 msgid "Save" msgstr "Guardar" -#: bookwyrm/templates/book/book.html:112 bookwyrm/templates/book/book.html:161 +#: bookwyrm/templates/book/book.html:126 bookwyrm/templates/book/book.html:175 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:238 +#: bookwyrm/templates/book/edit_book.html:241 #: bookwyrm/templates/edit_author.html:79 -#: bookwyrm/templates/moderation/report_modal.html:32 +#: bookwyrm/templates/moderation/report_modal.html:34 +#: bookwyrm/templates/settings/federated_server.html:94 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 #: bookwyrm/templates/snippets/readthrough.html:76 @@ -227,78 +214,93 @@ msgstr "Guardar" msgid "Cancel" msgstr "Cancelar" -#: bookwyrm/templates/book/book.html:121 +#: bookwyrm/templates/book/book.html:135 #, python-format msgid "%(count)s editions" msgstr "%(count)s ediciones" -#: bookwyrm/templates/book/book.html:129 +#: bookwyrm/templates/book/book.html:143 #, python-format msgid "This edition is on your %(shelf_name)s shelf." msgstr "Esta edición está en tu %(shelf_name)s estante." -#: bookwyrm/templates/book/book.html:135 +#: bookwyrm/templates/book/book.html:149 #, python-format msgid "A different edition of this book is on your %(shelf_name)s shelf." msgstr "Una edición diferente de este libro está en tu %(shelf_name)s estante." -#: bookwyrm/templates/book/book.html:144 +#: bookwyrm/templates/book/book.html:158 msgid "Your reading activity" msgstr "Tu actividad de lectura" -#: bookwyrm/templates/book/book.html:146 +#: bookwyrm/templates/book/book.html:160 msgid "Add read dates" msgstr "Agregar fechas de lectura" -#: bookwyrm/templates/book/book.html:151 +#: bookwyrm/templates/book/book.html:165 msgid "You don't have any reading activity for this book." msgstr "No tienes ninguna actividad de lectura para este libro." -#: bookwyrm/templates/book/book.html:158 +#: bookwyrm/templates/book/book.html:172 msgid "Create" msgstr "Crear" -#: bookwyrm/templates/book/book.html:180 +#: bookwyrm/templates/book/book.html:194 msgid "Subjects" msgstr "Sujetos" -#: bookwyrm/templates/book/book.html:191 +#: bookwyrm/templates/book/book.html:206 msgid "Places" msgstr "Lugares" -#: bookwyrm/templates/book/book.html:202 bookwyrm/templates/layout.html:64 +#: bookwyrm/templates/book/book.html:217 bookwyrm/templates/layout.html:65 #: bookwyrm/templates/lists/lists.html:5 bookwyrm/templates/lists/lists.html:12 #: bookwyrm/templates/search_results.html:91 #: bookwyrm/templates/user/user_layout.html:62 msgid "Lists" msgstr "Listas" -#: bookwyrm/templates/book/book.html:213 +#: bookwyrm/templates/book/book.html:228 msgid "Add to list" msgstr "Agregar a lista" -#: bookwyrm/templates/book/book.html:223 +#: bookwyrm/templates/book/book.html:238 #: bookwyrm/templates/book/cover_modal.html:31 -#: bookwyrm/templates/lists/list.html:156 +#: bookwyrm/templates/lists/list.html:123 msgid "Add" msgstr "Agregar" -#: bookwyrm/templates/book/book.html:251 +#: bookwyrm/templates/book/book.html:276 msgid "rated it" msgstr "lo calificó con" +#: bookwyrm/templates/book/book_identifiers.html:8 +msgid "ISBN:" +msgstr "ISBN:" + +#: bookwyrm/templates/book/book_identifiers.html:15 +#: bookwyrm/templates/book/edit_book.html:226 +msgid "OCLC Number:" +msgstr "Número OCLC:" + +#: bookwyrm/templates/book/book_identifiers.html:22 +#: bookwyrm/templates/book/edit_book.html:230 +msgid "ASIN:" +msgstr "ASIN:" + #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:175 +#: bookwyrm/templates/book/edit_book.html:178 msgid "Upload cover:" msgstr "Subir portada:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:181 +#: bookwyrm/templates/book/edit_book.html:184 msgid "Load cover from url:" msgstr "Agregar portada de url:" #: bookwyrm/templates/book/edit_book.html:5 #: bookwyrm/templates/book/edit_book.html:11 +#, python-format msgid "Edit \"%(book_title)s\"" msgstr "Editar \"%(book_title)s\"" @@ -332,6 +334,7 @@ msgid "Is \"%(name)s\" an existing author?" msgstr "¿Es \"%(name)s\" un autor ya existente?" #: bookwyrm/templates/book/edit_book.html:52 +#, python-format msgid "Author of %(book_title)s" msgstr "Autor de %(book_title)s" @@ -375,77 +378,78 @@ msgstr "Título:" msgid "Subtitle:" msgstr "Subtítulo:" -#: bookwyrm/templates/book/edit_book.html:112 +#: bookwyrm/templates/book/edit_book.html:113 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:120 msgid "Series number:" msgstr "Número de serie:" -#: bookwyrm/templates/book/edit_book.html:123 +#: bookwyrm/templates/book/edit_book.html:126 msgid "Publisher:" msgstr "Editorial:" -#: bookwyrm/templates/book/edit_book.html:125 +#: bookwyrm/templates/book/edit_book.html:128 msgid "Separate multiple publishers with commas." msgstr "Separar varios editores con comas." -#: bookwyrm/templates/book/edit_book.html:132 +#: bookwyrm/templates/book/edit_book.html:135 msgid "First published date:" msgstr "Fecha de primera publicación:" -#: bookwyrm/templates/book/edit_book.html:140 +#: bookwyrm/templates/book/edit_book.html:143 msgid "Published date:" msgstr "Fecha de publicación:" -#: bookwyrm/templates/book/edit_book.html:149 +#: bookwyrm/templates/book/edit_book.html:152 msgid "Authors" msgstr "Autores" -#: bookwyrm/templates/book/edit_book.html:155 +#: bookwyrm/templates/book/edit_book.html:158 +#, python-format msgid "Remove %(name)s" msgstr "Eliminar %(name)s" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:163 msgid "Add Authors:" msgstr "Agregar Autores:" -#: bookwyrm/templates/book/edit_book.html:161 +#: bookwyrm/templates/book/edit_book.html:164 msgid "John Doe, Jane Smith" msgstr "Juan Nadie, Natalia Natalia" -#: bookwyrm/templates/book/edit_book.html:167 +#: bookwyrm/templates/book/edit_book.html:170 #: bookwyrm/templates/user/shelf.html:75 msgid "Cover" msgstr "Portada:" -#: bookwyrm/templates/book/edit_book.html:194 +#: bookwyrm/templates/book/edit_book.html:197 msgid "Physical Properties" msgstr "Propiedades físicas:" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:198 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "Formato:" -#: bookwyrm/templates/book/edit_book.html:203 +#: bookwyrm/templates/book/edit_book.html:206 msgid "Pages:" msgstr "Páginas:" -#: bookwyrm/templates/book/edit_book.html:210 +#: bookwyrm/templates/book/edit_book.html:213 msgid "Book Identifiers" msgstr "Identificadores de libro" -#: bookwyrm/templates/book/edit_book.html:211 +#: bookwyrm/templates/book/edit_book.html:214 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:215 +#: bookwyrm/templates/book/edit_book.html:218 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:219 +#: bookwyrm/templates/book/edit_book.html:222 #: bookwyrm/templates/edit_author.html:59 msgid "Openlibrary key:" msgstr "Clave OpenLibrary:" @@ -469,30 +473,37 @@ msgstr "Cualquier" msgid "Language:" msgstr "Idioma:" -#: bookwyrm/templates/book/publisher_info.html:6 +#: bookwyrm/templates/book/publisher_info.html:22 +#, python-format +msgid "%(format)s" +msgstr "%(format)s" + +#: bookwyrm/templates/book/publisher_info.html:24 #, python-format msgid "%(format)s, %(pages)s pages" msgstr "%(format)s, %(pages)s páginas" -#: bookwyrm/templates/book/publisher_info.html:8 +#: bookwyrm/templates/book/publisher_info.html:26 #, python-format msgid "%(pages)s pages" msgstr "%(pages)s páginas" -#: bookwyrm/templates/book/publisher_info.html:13 +#: bookwyrm/templates/book/publisher_info.html:38 +#, python-format msgid "%(languages)s language" msgstr "idioma %(languages)s" -#: bookwyrm/templates/book/publisher_info.html:18 +#: bookwyrm/templates/book/publisher_info.html:64 #, python-format msgid "Published %(date)s by %(publisher)s." msgstr "Publicado %(date)s por %(publisher)s." -#: bookwyrm/templates/book/publisher_info.html:20 +#: bookwyrm/templates/book/publisher_info.html:66 +#, python-format msgid "Published %(date)s" msgstr "Publicado %(date)s" -#: bookwyrm/templates/book/publisher_info.html:22 +#: bookwyrm/templates/book/publisher_info.html:68 #, python-format msgid "Published by %(publisher)s." msgstr "Publicado por %(publisher)s." @@ -523,7 +534,7 @@ msgstr "Comunidad federalizada" #: bookwyrm/templates/directory/directory.html:6 #: bookwyrm/templates/directory/directory.html:11 -#: bookwyrm/templates/layout.html:92 +#: bookwyrm/templates/layout.html:93 msgid "Directory" msgstr "Directorio" @@ -532,6 +543,7 @@ msgid "Make your profile discoverable to other BookWyrm users." msgstr "Haz que tu perfil sea reconocible a otros usarios de BookWyrm." #: bookwyrm/templates/directory/directory.html:26 +#, python-format msgid "You can opt-out at any time in your profile settings." msgstr "Puedes optar por no en cualquier hora en tus configuraciones de perfil." @@ -646,7 +658,7 @@ msgid "Email address:" msgstr "Dirección de correo electrónico:" #: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:31 +#: bookwyrm/templates/moderation/report_modal.html:33 msgid "Submit" msgstr "Enviar" @@ -708,6 +720,7 @@ msgstr "Preferencia de correo electrónico" #: bookwyrm/templates/email/invite/html_content.html:6 #: bookwyrm/templates/email/invite/subject.html:2 +#, python-format msgid "You're invited to join %(site_name)s!" msgstr "¡Estás invitado a unirse con %(site_name)s!" @@ -749,6 +762,7 @@ msgid "If you didn't request to reset your password, you can ignore this email." msgstr "Si no solicitaste reestablecer tu contraseña, puedes ignorar este mensaje." #: bookwyrm/templates/email/password_reset/subject.html:2 +#, python-format msgid "Reset your %(site_name)s password" msgstr "Reestablece tu contraseña de %(site_name)s" @@ -758,7 +772,7 @@ msgid "Direct Messages with %(username)s" msgstr "Mensajes directos con %(username)s" #: bookwyrm/templates/feed/direct_messages.html:10 -#: bookwyrm/templates/layout.html:87 +#: bookwyrm/templates/layout.html:88 msgid "Direct Messages" msgstr "Mensajes directos" @@ -791,6 +805,7 @@ msgid "Local" msgstr "Local" #: bookwyrm/templates/feed/feed.html:25 +#: bookwyrm/templates/settings/edit_server.html:40 msgid "Federated" msgstr "Federalizado" @@ -813,7 +828,7 @@ msgid "Updates" msgstr "Actualizaciones" #: bookwyrm/templates/feed/feed_layout.html:11 -#: bookwyrm/templates/layout.html:58 +#: bookwyrm/templates/layout.html:59 #: bookwyrm/templates/user/books_header.html:3 msgid "Your books" msgstr "Tus libros" @@ -859,6 +874,7 @@ msgstr[0] "%(shared_books)s libro en tus estantes" msgstr[1] "%(shared_books)s libros en tus estantes" #: bookwyrm/templates/get_started/book_preview.html:6 +#, python-format msgid "Have you read %(book_title)s?" msgstr "¿Has leído %(book_title)s?" @@ -867,7 +883,7 @@ msgid "What are you reading?" msgstr "¿Qué estás leyendo?" #: bookwyrm/templates/get_started/books.html:9 -#: bookwyrm/templates/lists/list.html:124 +#: bookwyrm/templates/lists/list.html:91 msgid "Search for a book" msgstr "Buscar libros" @@ -887,8 +903,8 @@ msgstr "Puedes agregar libros cuando comiences a usar %(site_name)s." #: bookwyrm/templates/get_started/books.html:17 #: bookwyrm/templates/get_started/users.html:18 #: bookwyrm/templates/get_started/users.html:19 -#: bookwyrm/templates/layout.html:37 bookwyrm/templates/layout.html:38 -#: bookwyrm/templates/lists/list.html:128 +#: bookwyrm/templates/layout.html:38 bookwyrm/templates/layout.html:39 +#: bookwyrm/templates/lists/list.html:95 msgid "Search" msgstr "Buscar" @@ -897,11 +913,12 @@ msgid "Suggested Books" msgstr "Libros sugeridos" #: bookwyrm/templates/get_started/books.html:41 +#, python-format msgid "Popular on %(site_name)s" msgstr "Popular en %(site_name)s" #: bookwyrm/templates/get_started/books.html:51 -#: bookwyrm/templates/lists/list.html:141 +#: bookwyrm/templates/lists/list.html:108 msgid "No books found" msgstr "No se encontró ningún libro" @@ -911,6 +928,7 @@ msgid "Save & continue" msgstr "Guardar & continuar" #: bookwyrm/templates/get_started/layout.html:14 +#, python-format msgid "Welcome to %(site_name)s!" msgstr "¡Bienvenido a %(site_name)s!" @@ -1013,7 +1031,7 @@ msgid "%(username)s's %(year)s Books" msgstr "Los libros de %(username)s para %(year)s" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/layout.html:97 +#: bookwyrm/templates/layout.html:98 msgid "Import Books" msgstr "Importar libros" @@ -1034,6 +1052,7 @@ msgid "Privacy setting for imported reviews:" msgstr "Configuración de privacidad para las reseñas importadas:" #: bookwyrm/templates/import.html:48 +#: bookwyrm/templates/settings/server_blocklist.html:64 msgid "Import" msgstr "Importar" @@ -1140,94 +1159,96 @@ msgstr "Resultados de búsqueda por \"%(query)s\"" msgid "Matching Books" msgstr "Libros correspondientes" -#: bookwyrm/templates/layout.html:33 +#: bookwyrm/templates/layout.html:34 msgid "Search for a book or user" msgstr "Buscar un libro o un usuario" -#: bookwyrm/templates/layout.html:47 bookwyrm/templates/layout.html:48 +#: bookwyrm/templates/layout.html:48 bookwyrm/templates/layout.html:49 msgid "Main navigation menu" msgstr "Menú de navigación central" -#: bookwyrm/templates/layout.html:61 +#: bookwyrm/templates/layout.html:62 msgid "Feed" msgstr "Actividad" -#: bookwyrm/templates/layout.html:102 +#: bookwyrm/templates/layout.html:103 msgid "Settings" msgstr "Configuración" -#: bookwyrm/templates/layout.html:111 -#: bookwyrm/templates/settings/admin_layout.html:24 +#: bookwyrm/templates/layout.html:112 +#: bookwyrm/templates/settings/admin_layout.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:15 #: bookwyrm/templates/settings/manage_invites.html:3 #: bookwyrm/templates/settings/manage_invites.html:15 msgid "Invites" msgstr "Invitaciones" -#: bookwyrm/templates/layout.html:118 +#: bookwyrm/templates/layout.html:119 msgid "Admin" msgstr "Admin" -#: bookwyrm/templates/layout.html:125 +#: bookwyrm/templates/layout.html:126 msgid "Log out" msgstr "Cerrar sesión" -#: bookwyrm/templates/layout.html:133 bookwyrm/templates/layout.html:134 +#: bookwyrm/templates/layout.html:134 bookwyrm/templates/layout.html:135 #: bookwyrm/templates/notifications.html:6 #: bookwyrm/templates/notifications.html:10 msgid "Notifications" msgstr "Notificaciones" -#: bookwyrm/templates/layout.html:151 bookwyrm/templates/layout.html:155 +#: bookwyrm/templates/layout.html:152 bookwyrm/templates/layout.html:156 #: bookwyrm/templates/login.html:17 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nombre de usuario:" -#: bookwyrm/templates/layout.html:156 +#: bookwyrm/templates/layout.html:157 msgid "password" msgstr "contraseña" -#: bookwyrm/templates/layout.html:157 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:158 bookwyrm/templates/login.html:36 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" -#: bookwyrm/templates/layout.html:160 bookwyrm/templates/login.html:10 +#: bookwyrm/templates/layout.html:161 bookwyrm/templates/login.html:10 #: bookwyrm/templates/login.html:33 msgid "Log in" msgstr "Iniciar sesión" -#: bookwyrm/templates/layout.html:168 +#: bookwyrm/templates/layout.html:169 msgid "Join" msgstr "Unirse" -#: bookwyrm/templates/layout.html:191 +#: bookwyrm/templates/layout.html:195 msgid "About this server" msgstr "Sobre este servidor" -#: bookwyrm/templates/layout.html:195 +#: bookwyrm/templates/layout.html:199 msgid "Contact site admin" msgstr "Contactarse con administradores del sitio" -#: bookwyrm/templates/layout.html:202 +#: bookwyrm/templates/layout.html:206 #, python-format msgid "Support %(site_name)s on %(support_title)s" msgstr "Apoyar %(site_name)s en %(support_title)s" -#: bookwyrm/templates/layout.html:206 +#: bookwyrm/templates/layout.html:210 msgid "BookWyrm is open source software. You can contribute or report issues on GitHub." msgstr "BookWyrm es software de código abierto. Puedes contribuir o reportar problemas en GitHub." #: bookwyrm/templates/lists/create_form.html:5 -#: bookwyrm/templates/lists/lists.html:19 +#: bookwyrm/templates/lists/lists.html:20 msgid "Create List" msgstr "Crear lista" #: bookwyrm/templates/lists/created_text.html:5 +#, python-format msgid "Created and curated by %(username)s" msgstr "Agregado y comisariado por %(username)s" #: bookwyrm/templates/lists/created_text.html:7 +#, python-format msgid "Created by %(username)s" msgstr "Creado por %(username)s" @@ -1281,7 +1302,7 @@ msgid "Anyone can suggest books, subject to your approval" msgstr "Cualquier usuario puede sugerir libros, en cuanto lo hayas aprobado" #: bookwyrm/templates/lists/form.html:31 -#: bookwyrm/templates/moderation/reports.html:24 +#: bookwyrm/templates/moderation/reports.html:25 msgid "Open" msgstr "Abierto" @@ -1289,65 +1310,58 @@ msgstr "Abierto" msgid "Anyone can add books to this list" msgstr "Cualquer usuario puede agregar libros a esta lista" -#: bookwyrm/templates/lists/list.html:19 -#: bookwyrm/templates/snippets/pagination.html:12 -msgid "Previous" -msgstr "Anterior" - -#: bookwyrm/templates/lists/list.html:22 -#: bookwyrm/templates/snippets/pagination.html:23 -msgid "Next" -msgstr "Siguiente" - -#: bookwyrm/templates/lists/list.html:58 +#: bookwyrm/templates/lists/list.html:17 msgid "This list is currently empty" msgstr "Esta lista está vacia" -#: bookwyrm/templates/lists/list.html:76 +#: bookwyrm/templates/lists/list.html:36 #, python-format msgid "Added by %(username)s" msgstr "Agregado por %(username)s" -#: bookwyrm/templates/lists/list.html:82 +#: bookwyrm/templates/lists/list.html:48 +msgid "Set" +msgstr "Establecido" + +#: bookwyrm/templates/lists/list.html:51 +msgid "List position" +msgstr "Posición" + +#: bookwyrm/templates/lists/list.html:57 #: bookwyrm/templates/snippets/shelf_selector.html:26 msgid "Remove" msgstr "Quitar" -#: bookwyrm/templates/lists/list.html:90 -msgid "Set list position" -msgstr "Apunta indice" - -#: bookwyrm/templates/lists/list.html:103 -#: bookwyrm/templates/lists/list.html:115 +#: bookwyrm/templates/lists/list.html:70 bookwyrm/templates/lists/list.html:82 msgid "Sort List" msgstr "Ordena la lista" -#: bookwyrm/templates/lists/list.html:109 +#: bookwyrm/templates/lists/list.html:76 msgid "Direction" msgstr "Dirección" -#: bookwyrm/templates/lists/list.html:120 +#: bookwyrm/templates/lists/list.html:87 msgid "Add Books" msgstr "Agregar libros" -#: bookwyrm/templates/lists/list.html:120 +#: bookwyrm/templates/lists/list.html:87 msgid "Suggest Books" msgstr "Sugerir libros" -#: bookwyrm/templates/lists/list.html:129 +#: bookwyrm/templates/lists/list.html:96 msgid "search" msgstr "buscar" -#: bookwyrm/templates/lists/list.html:135 +#: bookwyrm/templates/lists/list.html:102 msgid "Clear search" msgstr "Borrar búsqueda" -#: bookwyrm/templates/lists/list.html:140 +#: bookwyrm/templates/lists/list.html:107 #, python-format msgid "No books found matching the query \"%(query)s\"" msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query)s\"" -#: bookwyrm/templates/lists/list.html:156 +#: bookwyrm/templates/lists/list.html:123 msgid "Suggest" msgstr "Sugerir" @@ -1372,71 +1386,50 @@ msgstr "Contactar a unx administradorx para recibir una invitación" msgid "More about this site" msgstr "Más sobre este sitio" -#: bookwyrm/templates/moderation/report.html:5 #: bookwyrm/templates/moderation/report.html:6 +#: bookwyrm/templates/moderation/report.html:7 #: bookwyrm/templates/moderation/report_preview.html:6 #, python-format msgid "Report #%(report_id)s: %(username)s" msgstr "Reportar #%(report_id)s: %(username)s" -#: bookwyrm/templates/moderation/report.html:10 +#: bookwyrm/templates/moderation/report.html:11 msgid "Back to reports" msgstr "Volver a los informes" -#: bookwyrm/templates/moderation/report.html:18 -msgid "Actions" -msgstr "Acciones" - -#: bookwyrm/templates/moderation/report.html:19 -msgid "View user profile" -msgstr "Ver perfil de usuario" - -#: bookwyrm/templates/moderation/report.html:22 -#: bookwyrm/templates/snippets/status/status_options.html:35 -#: bookwyrm/templates/snippets/user_options.html:13 -msgid "Send direct message" -msgstr "Enviar mensaje directo" - -#: bookwyrm/templates/moderation/report.html:27 -msgid "Deactivate user" -msgstr "Desactivar usuario" - -#: bookwyrm/templates/moderation/report.html:29 -msgid "Reactivate user" -msgstr "Reactivar usuario" - -#: bookwyrm/templates/moderation/report.html:36 +#: bookwyrm/templates/moderation/report.html:23 msgid "Moderator Comments" msgstr "Comentarios de moderador" -#: bookwyrm/templates/moderation/report.html:54 +#: bookwyrm/templates/moderation/report.html:41 #: bookwyrm/templates/snippets/create_status.html:28 -#: bookwyrm/templates/snippets/create_status_form.html:44 +#: bookwyrm/templates/snippets/create_status_form.html:53 msgid "Comment" msgstr "Comentario" -#: bookwyrm/templates/moderation/report.html:59 +#: bookwyrm/templates/moderation/report.html:46 msgid "Reported statuses" msgstr "Statuses reportados" -#: bookwyrm/templates/moderation/report.html:61 +#: bookwyrm/templates/moderation/report.html:48 msgid "No statuses reported" msgstr "Ningún estatus reportado" -#: bookwyrm/templates/moderation/report.html:67 +#: bookwyrm/templates/moderation/report.html:54 msgid "Status has been deleted" msgstr "Status ha sido eliminado" #: bookwyrm/templates/moderation/report_modal.html:6 +#, python-format msgid "Report @%(username)s" msgstr "Reportar @%(username)s" -#: bookwyrm/templates/moderation/report_modal.html:21 +#: bookwyrm/templates/moderation/report_modal.html:23 #, python-format msgid "This report will be sent to %(site_name)s's moderators for review." msgstr "Este informe se enviará a los moderadores de %(site_name)s para la revisión." -#: bookwyrm/templates/moderation/report_modal.html:22 +#: bookwyrm/templates/moderation/report_modal.html:24 msgid "More info about this report:" msgstr "Más información sobre este informe:" @@ -1445,6 +1438,7 @@ msgid "No notes provided" msgstr "No se proporcionó notas" #: bookwyrm/templates/moderation/report_preview.html:20 +#, python-format msgid "Reported by %(username)s" msgstr "Reportado por %(username)s" @@ -1457,24 +1451,26 @@ msgid "Resolve" msgstr "Resolver" #: bookwyrm/templates/moderation/reports.html:6 +#, python-format msgid "Reports: %(server_name)s" msgstr "Informes: %(server_name)s" #: bookwyrm/templates/moderation/reports.html:8 -#: bookwyrm/templates/moderation/reports.html:16 -#: bookwyrm/templates/settings/admin_layout.html:28 +#: bookwyrm/templates/moderation/reports.html:17 +#: bookwyrm/templates/settings/admin_layout.html:35 msgid "Reports" msgstr "Informes" -#: bookwyrm/templates/moderation/reports.html:13 +#: bookwyrm/templates/moderation/reports.html:14 +#, python-format msgid "Reports: %(server_name)s" msgstr "Informes: %(server_name)s" -#: bookwyrm/templates/moderation/reports.html:27 +#: bookwyrm/templates/moderation/reports.html:28 msgid "Resolved" msgstr "Resuelto" -#: bookwyrm/templates/moderation/reports.html:34 +#: bookwyrm/templates/moderation/reports.html:37 msgid "No reports found." msgstr "No se encontró ningún informe." @@ -1683,118 +1679,187 @@ msgstr "No se encontró ningúna lista correspondiente a \"%(query)s\"" msgid "Administration" msgstr "Adminstración" -#: bookwyrm/templates/settings/admin_layout.html:15 +#: bookwyrm/templates/settings/admin_layout.html:22 msgid "Manage Users" msgstr "Administrar usuarios" -#: bookwyrm/templates/settings/admin_layout.html:19 -#: bookwyrm/templates/settings/user_admin.html:3 -#: bookwyrm/templates/settings/user_admin.html:10 +#: bookwyrm/templates/settings/admin_layout.html:26 +#: bookwyrm/templates/user_admin/user_admin.html:3 +#: bookwyrm/templates/user_admin/user_admin.html:10 msgid "Users" msgstr "Usuarios" -#: bookwyrm/templates/settings/admin_layout.html:32 +#: bookwyrm/templates/settings/admin_layout.html:39 #: bookwyrm/templates/settings/federation.html:3 #: bookwyrm/templates/settings/federation.html:5 msgid "Federated Servers" msgstr "Servidores federalizados" -#: bookwyrm/templates/settings/admin_layout.html:37 +#: bookwyrm/templates/settings/admin_layout.html:44 msgid "Instance Settings" msgstr "Configuración de instancia" -#: bookwyrm/templates/settings/admin_layout.html:41 +#: bookwyrm/templates/settings/admin_layout.html:48 #: bookwyrm/templates/settings/site.html:4 #: bookwyrm/templates/settings/site.html:6 msgid "Site Settings" msgstr "Configuración de sitio" -#: bookwyrm/templates/settings/admin_layout.html:44 +#: bookwyrm/templates/settings/admin_layout.html:51 #: bookwyrm/templates/settings/site.html:13 msgid "Instance Info" msgstr "Información de instancia" -#: bookwyrm/templates/settings/admin_layout.html:45 +#: bookwyrm/templates/settings/admin_layout.html:52 #: bookwyrm/templates/settings/site.html:39 msgid "Images" msgstr "Imagenes" -#: bookwyrm/templates/settings/admin_layout.html:46 +#: bookwyrm/templates/settings/admin_layout.html:53 #: bookwyrm/templates/settings/site.html:59 msgid "Footer Content" msgstr "Contenido del pie de página" -#: bookwyrm/templates/settings/admin_layout.html:47 +#: bookwyrm/templates/settings/admin_layout.html:54 #: bookwyrm/templates/settings/site.html:77 msgid "Registration" msgstr "Registración" -#: bookwyrm/templates/settings/federated_server.html:7 +#: bookwyrm/templates/settings/edit_server.html:3 +#: bookwyrm/templates/settings/edit_server.html:6 +#: bookwyrm/templates/settings/edit_server.html:20 +#: bookwyrm/templates/settings/federation.html:9 +#: bookwyrm/templates/settings/federation.html:10 +#: bookwyrm/templates/settings/server_blocklist.html:3 +#: bookwyrm/templates/settings/server_blocklist.html:20 +msgid "Add server" +msgstr "Agregar servidor" + +#: bookwyrm/templates/settings/edit_server.html:7 +#: bookwyrm/templates/settings/federated_server.html:12 +#: bookwyrm/templates/settings/server_blocklist.html:7 msgid "Back to server list" msgstr "Volver a la lista de servidores" -#: bookwyrm/templates/settings/federated_server.html:12 -msgid "Details" -msgstr "Detalles" +#: bookwyrm/templates/settings/edit_server.html:16 +#: bookwyrm/templates/settings/server_blocklist.html:16 +msgid "Import block list" +msgstr "Importar lista de bloqueo" -#: bookwyrm/templates/settings/federated_server.html:15 -msgid "Software:" -msgstr "Software:" +#: bookwyrm/templates/settings/edit_server.html:30 +msgid "Instance:" +msgstr "Instancia:" -#: bookwyrm/templates/settings/federated_server.html:19 -msgid "Version:" -msgstr "Versión:" - -#: bookwyrm/templates/settings/federated_server.html:23 +#: bookwyrm/templates/settings/edit_server.html:37 +#: bookwyrm/templates/settings/federated_server.html:29 +#: bookwyrm/templates/user_admin/user_info.html:34 msgid "Status:" msgstr "Status:" -#: bookwyrm/templates/settings/federated_server.html:30 +#: bookwyrm/templates/settings/edit_server.html:41 +#: bookwyrm/templates/settings/federated_server.html:9 +msgid "Blocked" +msgstr "Bloqueado" + +#: bookwyrm/templates/settings/edit_server.html:48 +#: bookwyrm/templates/settings/federated_server.html:21 +#: bookwyrm/templates/user_admin/user_info.html:26 +msgid "Software:" +msgstr "Software:" + +#: bookwyrm/templates/settings/edit_server.html:55 +#: bookwyrm/templates/settings/federated_server.html:25 +#: bookwyrm/templates/user_admin/user_info.html:30 +msgid "Version:" +msgstr "Versión:" + +#: bookwyrm/templates/settings/edit_server.html:64 +msgid "Notes:" +msgstr "Notas:" + +#: bookwyrm/templates/settings/federated_server.html:18 +msgid "Details" +msgstr "Detalles" + +#: bookwyrm/templates/settings/federated_server.html:36 #: bookwyrm/templates/user/user_layout.html:50 msgid "Activity" msgstr "Actividad" -#: bookwyrm/templates/settings/federated_server.html:33 +#: bookwyrm/templates/settings/federated_server.html:39 msgid "Users:" msgstr "Usuarios:" -#: bookwyrm/templates/settings/federated_server.html:36 -#: bookwyrm/templates/settings/federated_server.html:43 +#: bookwyrm/templates/settings/federated_server.html:42 +#: bookwyrm/templates/settings/federated_server.html:49 msgid "View all" msgstr "Ver todos" -#: bookwyrm/templates/settings/federated_server.html:40 +#: bookwyrm/templates/settings/federated_server.html:46 msgid "Reports:" msgstr "Informes:" -#: bookwyrm/templates/settings/federated_server.html:47 +#: bookwyrm/templates/settings/federated_server.html:53 msgid "Followed by us:" msgstr "Seguido por nosotros:" -#: bookwyrm/templates/settings/federated_server.html:53 +#: bookwyrm/templates/settings/federated_server.html:59 msgid "Followed by them:" msgstr "Seguido por ellos:" -#: bookwyrm/templates/settings/federated_server.html:59 +#: bookwyrm/templates/settings/federated_server.html:65 msgid "Blocked by us:" msgstr "Bloqueado por nosotros:" -#: bookwyrm/templates/settings/federation.html:13 +#: bookwyrm/templates/settings/federated_server.html:77 +#: bookwyrm/templates/user_admin/user_info.html:39 +msgid "Notes" +msgstr "Notas" + +#: bookwyrm/templates/settings/federated_server.html:80 +msgid "Edit" +msgstr "Editar" + +#: bookwyrm/templates/settings/federated_server.html:100 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:3 +msgid "Actions" +msgstr "Acciones" + +#: bookwyrm/templates/settings/federated_server.html:104 +#: bookwyrm/templates/snippets/block_button.html:5 +msgid "Block" +msgstr "Bloquear" + +#: bookwyrm/templates/settings/federated_server.html:105 +msgid "All users from this instance will be deactivated." +msgstr "Todos los usuarios en esta instancia serán desactivados." + +#: bookwyrm/templates/settings/federated_server.html:110 +#: bookwyrm/templates/snippets/block_button.html:10 +msgid "Un-block" +msgstr "Desbloquear" + +#: bookwyrm/templates/settings/federated_server.html:111 +msgid "All users from this instance will be re-activated." +msgstr "Todos los usuarios en esta instancia serán re-activados." + +#: bookwyrm/templates/settings/federation.html:20 +#: bookwyrm/templates/user_admin/server_filter.html:5 msgid "Server name" msgstr "Nombre de servidor" -#: bookwyrm/templates/settings/federation.html:17 +#: bookwyrm/templates/settings/federation.html:24 msgid "Date federated" msgstr "Fecha de federalización" -#: bookwyrm/templates/settings/federation.html:21 +#: bookwyrm/templates/settings/federation.html:28 msgid "Software" msgstr "Software" -#: bookwyrm/templates/settings/federation.html:24 +#: bookwyrm/templates/settings/federation.html:31 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 -#: bookwyrm/templates/settings/user_admin.html:32 +#: bookwyrm/templates/user_admin/user_admin.html:34 msgid "Status" msgstr "Status" @@ -1904,6 +1969,23 @@ msgstr "Número de usos" msgid "No active invites" msgstr "No invitaciónes activas" +#: bookwyrm/templates/settings/server_blocklist.html:6 +msgid "Import Blocklist" +msgstr "Importar lista de bloqueo" + +#: bookwyrm/templates/settings/server_blocklist.html:26 +#: bookwyrm/templates/snippets/goal_progress.html:5 +msgid "Success!" +msgstr "¡Meta logrado!" + +#: bookwyrm/templates/settings/server_blocklist.html:30 +msgid "Successfully blocked:" +msgstr "Se bloqueó exitosamente:" + +#: bookwyrm/templates/settings/server_blocklist.html:32 +msgid "Failed:" +msgstr "Falló:" + #: bookwyrm/templates/settings/site.html:15 msgid "Instance Name:" msgstr "Nombre de instancia:" @@ -1960,46 +2042,10 @@ msgstr "Permitir solicitudes de invitación:" msgid "Registration closed text:" msgstr "Texto de registración cerrada:" -#: bookwyrm/templates/settings/user_admin.html:7 -#, python-format -msgid "Users: %(server_name)s" -msgstr "Usuarios %(server_name)s" - -#: bookwyrm/templates/settings/user_admin.html:20 -msgid "Username" -msgstr "Nombre de usuario" - -#: bookwyrm/templates/settings/user_admin.html:24 -msgid "Date Added" -msgstr "Fecha agregada" - -#: bookwyrm/templates/settings/user_admin.html:28 -msgid "Last Active" -msgstr "Actividad reciente" - -#: bookwyrm/templates/settings/user_admin.html:36 -msgid "Remote server" -msgstr "Quitar servidor" - -#: bookwyrm/templates/settings/user_admin.html:45 -msgid "Active" -msgstr "Activ@" - -#: bookwyrm/templates/settings/user_admin.html:45 -msgid "Inactive" -msgstr "Inactiv@" - -#: bookwyrm/templates/settings/user_admin.html:50 -msgid "Not set" -msgstr "No establecido" - -#: bookwyrm/templates/snippets/block_button.html:5 -msgid "Block" -msgstr "Bloquear" - -#: bookwyrm/templates/snippets/block_button.html:10 -msgid "Un-block" -msgstr "Desbloquear" +#: bookwyrm/templates/snippets/book_cover.html:20 +#: bookwyrm/templates/snippets/search_result_text.html:10 +msgid "No cover" +msgstr "Sin portada" #: bookwyrm/templates/snippets/book_titleby.html:3 #, python-format @@ -2008,8 +2054,8 @@ msgstr "%(title)s por " #: bookwyrm/templates/snippets/boost_button.html:8 #: bookwyrm/templates/snippets/boost_button.html:9 -#: bookwyrm/templates/snippets/status/status_body.html:52 -#: bookwyrm/templates/snippets/status/status_body.html:53 +#: bookwyrm/templates/snippets/status/layout.html:47 +#: bookwyrm/templates/snippets/status/layout.html:48 msgid "Boost status" msgstr "Status de respaldo" @@ -2034,53 +2080,60 @@ msgstr "Reseña" msgid "Quote" msgstr "Cita" -#: bookwyrm/templates/snippets/create_status_form.html:18 +#: bookwyrm/templates/snippets/create_status_form.html:20 msgid "Comment:" msgstr "Comentario:" -#: bookwyrm/templates/snippets/create_status_form.html:20 +#: bookwyrm/templates/snippets/create_status_form.html:22 msgid "Quote:" msgstr "Cita:" -#: bookwyrm/templates/snippets/create_status_form.html:22 +#: bookwyrm/templates/snippets/create_status_form.html:24 msgid "Review:" msgstr "Reseña:" -#: bookwyrm/templates/snippets/create_status_form.html:56 +#: bookwyrm/templates/snippets/create_status_form.html:42 +#: bookwyrm/templates/snippets/status/layout.html:30 +#: bookwyrm/templates/snippets/status/layout.html:43 +#: bookwyrm/templates/snippets/status/layout.html:44 +msgid "Reply" +msgstr "Respuesta" + +#: bookwyrm/templates/snippets/create_status_form.html:67 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 msgid "Progress:" msgstr "Progreso:" -#: bookwyrm/templates/snippets/create_status_form.html:63 +#: bookwyrm/templates/snippets/create_status_form.html:75 #: bookwyrm/templates/snippets/readthrough_form.html:22 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "páginas" -#: bookwyrm/templates/snippets/create_status_form.html:64 +#: bookwyrm/templates/snippets/create_status_form.html:76 #: bookwyrm/templates/snippets/readthrough_form.html:23 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "por ciento" -#: bookwyrm/templates/snippets/create_status_form.html:69 +#: bookwyrm/templates/snippets/create_status_form.html:82 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "de %(pages)s páginas" -#: bookwyrm/templates/snippets/create_status_form.html:81 +#: bookwyrm/templates/snippets/create_status_form.html:97 msgid "Include spoiler alert" msgstr "Incluir alerta de spoiler" -#: bookwyrm/templates/snippets/create_status_form.html:88 +#: bookwyrm/templates/snippets/create_status_form.html:104 #: bookwyrm/templates/snippets/privacy-icons.html:15 #: bookwyrm/templates/snippets/privacy-icons.html:16 #: bookwyrm/templates/snippets/privacy_select.html:19 msgid "Private" msgstr "Privada" -#: bookwyrm/templates/snippets/create_status_form.html:99 +#: bookwyrm/templates/snippets/create_status_form.html:115 msgid "Post" msgstr "Compartir" @@ -2095,14 +2148,13 @@ msgstr "Estás eliminando esta lectura y sus %(count)s actualizaciones de progre #: bookwyrm/templates/snippets/delete_readthrough_modal.html:15 #: bookwyrm/templates/snippets/follow_request_buttons.html:13 -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:391 msgid "Delete" msgstr "Eliminar" #: bookwyrm/templates/snippets/fav_button.html:7 #: bookwyrm/templates/snippets/fav_button.html:8 -#: bookwyrm/templates/snippets/status/status_body.html:56 -#: bookwyrm/templates/snippets/status/status_body.html:57 +#: bookwyrm/templates/snippets/status/layout.html:51 +#: bookwyrm/templates/snippets/status/layout.html:52 msgid "Like status" msgstr "Me gusta status" @@ -2164,6 +2216,7 @@ msgstr[0] "estableció una meta de leer %(counter)s libro en %(year)s" msgstr[1] "estableció una meta de leer %(counter)s libros en %(year)s" #: bookwyrm/templates/snippets/generated_status/rating.html:3 +#, python-format msgid "Rated %(title)s: %(display_rating)s star" msgid_plural "Rated %(title)s: %(display_rating)s stars" msgstr[0] "Reseño %(title)s: %(display_rating)s estrella" @@ -2209,10 +2262,6 @@ msgstr "Compartir con tu feed" msgid "Set goal" msgstr "Establecer meta" -#: bookwyrm/templates/snippets/goal_progress.html:5 -msgid "Success!" -msgstr "¡Meta logrado!" - #: bookwyrm/templates/snippets/goal_progress.html:7 #, python-format msgid "%(percent)s%% complete!" @@ -2229,6 +2278,7 @@ msgid "%(username)s has read %(read_count)s of %(goal_count msgstr "%(username)s ha leído %(read_count)s de %(goal_count)s libros." #: bookwyrm/templates/snippets/page_text.html:4 +#, python-format msgid "page %(page)s of %(total_pages)s" msgstr "página %(page)s de %(total_pages)s" @@ -2236,6 +2286,14 @@ msgstr "página %(page)s de %(total_pages)s" msgid "page %(page)s" msgstr "página %(pages)s" +#: bookwyrm/templates/snippets/pagination.html:12 +msgid "Previous" +msgstr "Anterior" + +#: bookwyrm/templates/snippets/pagination.html:23 +msgid "Next" +msgstr "Siguiente" + #: bookwyrm/templates/snippets/privacy-icons.html:3 #: bookwyrm/templates/snippets/privacy-icons.html:4 #: bookwyrm/templates/snippets/privacy_select.html:10 @@ -2322,29 +2380,25 @@ msgid "Report" msgstr "Reportar" #: bookwyrm/templates/snippets/rss_title.html:5 -#: bookwyrm/templates/snippets/status/status_header.html:11 +#: bookwyrm/templates/snippets/status/status_header.html:21 msgid "rated" msgstr "calificó" #: bookwyrm/templates/snippets/rss_title.html:7 -#: bookwyrm/templates/snippets/status/status_header.html:13 +#: bookwyrm/templates/snippets/status/status_header.html:23 msgid "reviewed" msgstr "reseñó" #: bookwyrm/templates/snippets/rss_title.html:9 -#: bookwyrm/templates/snippets/status/status_header.html:15 +#: bookwyrm/templates/snippets/status/status_header.html:25 msgid "commented on" msgstr "comentó en" #: bookwyrm/templates/snippets/rss_title.html:11 -#: bookwyrm/templates/snippets/status/status_header.html:17 +#: bookwyrm/templates/snippets/status/status_header.html:27 msgid "quoted" msgstr "citó" -#: bookwyrm/templates/snippets/search_result_text.html:10 -msgid "No cover" -msgstr "Sin portada" - #: bookwyrm/templates/snippets/search_result_text.html:22 #, python-format msgid "by %(author)s" @@ -2364,7 +2418,7 @@ msgid "Finish \"%(book_title)s\"" msgstr "Terminar \"%(book_title)s\"" #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:35 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:34 msgid "Update progress" msgstr "Progreso de actualización" @@ -2385,7 +2439,8 @@ msgstr "Terminar de leer" msgid "Want to read" msgstr "Quiero leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 +#, python-format msgid "Remove from %(name)s" msgstr "Quitar de %(name)s" @@ -2399,48 +2454,49 @@ msgstr "Empezar \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" msgstr "Quiero leer \"%(book_title)s\"" -#: bookwyrm/templates/snippets/status/status.html:9 -msgid "boosted" -msgstr "respaldó" +#: bookwyrm/templates/snippets/status/content_status.html:60 +#: bookwyrm/templates/snippets/status/status_content.html:50 +#: bookwyrm/templates/snippets/trimmed_text.html:14 +msgid "Show more" +msgstr "Mostrar más" -#: bookwyrm/templates/snippets/status/status_body.html:27 +#: bookwyrm/templates/snippets/status/content_status.html:75 +#: bookwyrm/templates/snippets/status/status_content.html:65 +#: bookwyrm/templates/snippets/trimmed_text.html:29 +msgid "Show less" +msgstr "Mostrar menos" + +#: bookwyrm/templates/snippets/status/content_status.html:105 +#: bookwyrm/templates/snippets/status/status_content.html:95 +msgid "Open image in new window" +msgstr "Abrir imagen en una nueva ventana" + +#: bookwyrm/templates/snippets/status/layout.html:22 #: bookwyrm/templates/snippets/status/status_options.html:18 msgid "Delete status" msgstr "Eliminar status" -#: bookwyrm/templates/snippets/status/status_body.html:35 -#: bookwyrm/templates/snippets/status/status_body.html:48 -#: bookwyrm/templates/snippets/status/status_body.html:49 -msgid "Reply" -msgstr "Respuesta" +#: bookwyrm/templates/snippets/status/status.html:9 +msgid "boosted" +msgstr "respaldó" -#: bookwyrm/templates/snippets/status/status_content.html:18 -#: bookwyrm/templates/snippets/trimmed_text.html:15 -msgid "Show more" -msgstr "Mostrar más" - -#: bookwyrm/templates/snippets/status/status_content.html:25 -#: bookwyrm/templates/snippets/trimmed_text.html:25 -msgid "Show less" -msgstr "Mostrar menos" - -#: bookwyrm/templates/snippets/status/status_content.html:46 -msgid "Open image in new window" -msgstr "Abrir imagen en una nueva ventana" - -#: bookwyrm/templates/snippets/status/status_header.html:22 +#: bookwyrm/templates/snippets/status/status_header.html:32 +#, python-format msgid "replied to %(username)s's review" msgstr "respondió a la reseña de %(username)s " -#: bookwyrm/templates/snippets/status/status_header.html:24 +#: bookwyrm/templates/snippets/status/status_header.html:34 +#, python-format msgid "replied to %(username)s's comment" msgstr "respondió al comentario de %(username)s " -#: bookwyrm/templates/snippets/status/status_header.html:26 +#: bookwyrm/templates/snippets/status/status_header.html:36 +#, python-format msgid "replied to %(username)s's quote" msgstr "respondió a la cita de %(username)s " -#: bookwyrm/templates/snippets/status/status_header.html:28 +#: bookwyrm/templates/snippets/status/status_header.html:38 +#, python-format msgid "replied to %(username)s's status" msgstr "respondió al status de %(username)s " @@ -2453,6 +2509,12 @@ msgstr "Más opciones" msgid "Delete & re-draft" msgstr "Eliminar y recomponer" +#: bookwyrm/templates/snippets/status/status_options.html:36 +#: bookwyrm/templates/snippets/user_options.html:13 +#: bookwyrm/templates/user_admin/user_moderation_actions.html:6 +msgid "Send direct message" +msgstr "Enviar mensaje directo" + #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" msgstr "Cambiar a esta edición" @@ -2479,6 +2541,7 @@ msgid "Books tagged \"%(tag.name)s\"" msgstr "Libros etiquetados con \"%(tag.name)s\"" #: bookwyrm/templates/user/books_header.html:5 +#, python-format msgid "%(username)s's books" msgstr "Los libros de %(username)s" @@ -2524,7 +2587,7 @@ msgstr "Listas: %(username)s" msgid "Create list" msgstr "Crear lista" -#: bookwyrm/templates/user/shelf.html:24 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf.html:24 bookwyrm/views/shelf.py:51 msgid "All books" msgstr "Todos los libros" @@ -2561,6 +2624,7 @@ msgid "Edit profile" msgstr "Editar perfil" #: bookwyrm/templates/user/user.html:34 +#, python-format msgid "View all %(size)s" msgstr "Ver todos los %(size)s" @@ -2614,6 +2678,73 @@ msgstr[1] "%(counter)s seguidores" msgid "%(counter)s following" msgstr "%(counter)s siguiendo" +#: bookwyrm/templates/user_admin/user.html:11 +msgid "Back to users" +msgstr "Volver a usuarios" + +#: bookwyrm/templates/user_admin/user_admin.html:7 +#, python-format +msgid "Users: %(server_name)s" +msgstr "Usuarios %(server_name)s" + +#: bookwyrm/templates/user_admin/user_admin.html:22 +#: bookwyrm/templates/user_admin/username_filter.html:5 +msgid "Username" +msgstr "Nombre de usuario" + +#: bookwyrm/templates/user_admin/user_admin.html:26 +msgid "Date Added" +msgstr "Fecha agregada" + +#: bookwyrm/templates/user_admin/user_admin.html:30 +msgid "Last Active" +msgstr "Actividad reciente" + +#: bookwyrm/templates/user_admin/user_admin.html:38 +msgid "Remote server" +msgstr "Quitar servidor" + +#: bookwyrm/templates/user_admin/user_admin.html:47 +msgid "Active" +msgstr "Activ@" + +#: bookwyrm/templates/user_admin/user_admin.html:47 +msgid "Inactive" +msgstr "Inactiv@" + +#: bookwyrm/templates/user_admin/user_admin.html:52 +#: bookwyrm/templates/user_admin/user_info.html:49 +msgid "Not set" +msgstr "No establecido" + +#: bookwyrm/templates/user_admin/user_info.html:5 +msgid "User details" +msgstr "Detalles" + +#: bookwyrm/templates/user_admin/user_info.html:14 +msgid "View user profile" +msgstr "Ver perfil de usuario" + +#: bookwyrm/templates/user_admin/user_info.html:20 +msgid "Instance details" +msgstr "Detalles de instancia" + +#: bookwyrm/templates/user_admin/user_info.html:46 +msgid "View instance" +msgstr "Ver instancia" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:11 +msgid "Suspend user" +msgstr "Suspender usuario" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:13 +msgid "Un-suspend user" +msgstr "Des-suspender usuario" + +#: bookwyrm/templates/user_admin/user_moderation_actions.html:21 +msgid "Access level:" +msgstr "Nivel de acceso:" + #: bookwyrm/views/password.py:32 msgid "No user with that email address was found." msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónico." @@ -2623,1253 +2754,872 @@ msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónic msgid "A password reset link sent to %s" msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" -#: venv/lib/python3.8/site-packages/_pytest/config/argparsing.py:442 -#, python-format -msgid "ambiguous option: %(option)s could match %(matches)s" -msgstr "opción ambiguo: %(option)s pudiera coincidir con %(matches)s" +#~ msgid "Deactivate user" +#~ msgstr "Desactivar usuario" -#: venv/lib/python3.8/site-packages/django/contrib/messages/apps.py:7 -msgid "Messages" -msgstr "Mensajes" +#~ msgid "Reactivate user" +#~ msgstr "Reactivar usuario" -#: venv/lib/python3.8/site-packages/django/contrib/sitemaps/apps.py:7 -msgid "Site Maps" -msgstr "Mapas de sitio" +#~ msgid "ambiguous option: %(option)s could match %(matches)s" +#~ msgstr "opción ambiguo: %(option)s pudiera coincidir con %(matches)s" -#: venv/lib/python3.8/site-packages/django/contrib/staticfiles/apps.py:9 -msgid "Static Files" -msgstr "Archivos estáticos" +#~ msgid "Messages" +#~ msgstr "Mensajes" -#: venv/lib/python3.8/site-packages/django/contrib/syndication/apps.py:7 -msgid "Syndication" -msgstr "Sindicación" +#~ msgid "Site Maps" +#~ msgstr "Mapas de sitio" -#: venv/lib/python3.8/site-packages/django/core/paginator.py:48 -msgid "That page number is not an integer" -msgstr "Ese numero de pagina no es un entero" +#~ msgid "Static Files" +#~ msgstr "Archivos estáticos" -#: venv/lib/python3.8/site-packages/django/core/paginator.py:50 -msgid "That page number is less than 1" -msgstr "Ese numero de pagina es menos que uno" +#~ msgid "Syndication" +#~ msgstr "Sindicación" -#: venv/lib/python3.8/site-packages/django/core/paginator.py:55 -msgid "That page contains no results" -msgstr "Esa pagina no contiene resultados" +#~ msgid "That page number is not an integer" +#~ msgstr "Ese numero de pagina no es un entero" -#: venv/lib/python3.8/site-packages/django/core/validators.py:20 -msgid "Enter a valid value." -msgstr "Ingrese un valor válido." +#~ msgid "That page number is less than 1" +#~ msgstr "Ese numero de pagina es menos que uno" -#: venv/lib/python3.8/site-packages/django/core/validators.py:91 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:671 -msgid "Enter a valid URL." -msgstr "Ingrese una URL válida." +#~ msgid "That page contains no results" +#~ msgstr "Esa pagina no contiene resultados" -#: venv/lib/python3.8/site-packages/django/core/validators.py:145 -msgid "Enter a valid integer." -msgstr "Ingrese un entero válido." +#~ msgid "Enter a valid value." +#~ msgstr "Ingrese un valor válido." -#: venv/lib/python3.8/site-packages/django/core/validators.py:156 -msgid "Enter a valid email address." -msgstr "Ingrese una dirección de correo electrónico válida." +#~ msgid "Enter a valid URL." +#~ msgstr "Ingrese una URL válida." -#. Translators: "letters" means latin letters: a-z and A-Z. -#: venv/lib/python3.8/site-packages/django/core/validators.py:230 -msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." -msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones" +#~ msgid "Enter a valid integer." +#~ msgstr "Ingrese un entero válido." -#: venv/lib/python3.8/site-packages/django/core/validators.py:237 -msgid "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens." -msgstr "Ingrese un “slug” válido que consiste de letras Unicode, numeros, guiones bajos, o guiones" +#~ msgid "Enter a valid email address." +#~ msgstr "Ingrese una dirección de correo electrónico válida." -#: venv/lib/python3.8/site-packages/django/core/validators.py:246 -#: venv/lib/python3.8/site-packages/django/core/validators.py:266 -msgid "Enter a valid IPv4 address." -msgstr "Ingrese una dirección IPv4 válida." +#~ msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +#~ msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones" -#: venv/lib/python3.8/site-packages/django/core/validators.py:251 -#: venv/lib/python3.8/site-packages/django/core/validators.py:267 -msgid "Enter a valid IPv6 address." -msgstr "Ingrese una dirección IPv6 válida." +#~ msgid "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens." +#~ msgstr "Ingrese un “slug” válido que consiste de letras Unicode, numeros, guiones bajos, o guiones" -#: venv/lib/python3.8/site-packages/django/core/validators.py:261 -#: venv/lib/python3.8/site-packages/django/core/validators.py:265 -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Ingrese una dirección IPv4 o IPv6 válida." +#~ msgid "Enter a valid IPv4 address." +#~ msgstr "Ingrese una dirección IPv4 válida." -#: venv/lib/python3.8/site-packages/django/core/validators.py:295 -msgid "Enter only digits separated by commas." -msgstr "Ingrese solo digitos separados por comas." +#~ msgid "Enter a valid IPv6 address." +#~ msgstr "Ingrese una dirección IPv6 válida." -#: venv/lib/python3.8/site-packages/django/core/validators.py:301 -#, python-format -msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "Asegura que este valor es %(limit_value)s (es %(show_value)s)." +#~ msgid "Enter a valid IPv4 or IPv6 address." +#~ msgstr "Ingrese una dirección IPv4 o IPv6 válida." -#: venv/lib/python3.8/site-packages/django/core/validators.py:334 -#, python-format -msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "Asegura que este valor es menor que o iguala a %(limit_value)s." +#~ msgid "Enter only digits separated by commas." +#~ msgstr "Ingrese solo digitos separados por comas." -#: venv/lib/python3.8/site-packages/django/core/validators.py:343 -#, python-format -msgid "Ensure this value is greater than or equal to %(limit_value)s." -msgstr "Asegura que este valor es más que o que iguala a %(limit_value)s." +#~ msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +#~ msgstr "Asegura que este valor es %(limit_value)s (es %(show_value)s)." -#: venv/lib/python3.8/site-packages/django/core/validators.py:353 -#, python-format -msgid "Ensure this value has at least %(limit_value)d character (it has %(show_value)d)." -msgid_plural "Ensure this value has at least %(limit_value)d characters (it has %(show_value)d)." -msgstr[0] "Verifica que este valor tiene por lo menos %(limit_value)d carácter. (Tiene %(show_value)d).)" -msgstr[1] "Verifica que este valor tiene por lo menos %(limit_value)d caracteres. (Tiene %(show_value)d).)" +#~ msgid "Ensure this value is less than or equal to %(limit_value)s." +#~ msgstr "Asegura que este valor es menor que o iguala a %(limit_value)s." -#: venv/lib/python3.8/site-packages/django/core/validators.py:368 -#, python-format -msgid "Ensure this value has at most %(limit_value)d character (it has %(show_value)d)." -msgid_plural "Ensure this value has at most %(limit_value)d characters (it has %(show_value)d)." -msgstr[0] "Verifica que este valor tiene a lo sumo %(limit_value)d carácter. (Tiene %(show_value)d).)" -msgstr[1] "Verifica que este valor tiene a lo sumo %(limit_value)d caracteres. (Tiene %(show_value)d).)" +#~ msgid "Ensure this value is greater than or equal to %(limit_value)s." +#~ msgstr "Asegura que este valor es más que o que iguala a %(limit_value)s." -#: venv/lib/python3.8/site-packages/django/core/validators.py:387 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:292 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:327 -msgid "Enter a number." -msgstr "Ingrese un número." +#~ msgid "Ensure this value has at least %(limit_value)d character (it has %(show_value)d)." +#~ msgid_plural "Ensure this value has at least %(limit_value)d characters (it has %(show_value)d)." +#~ msgstr[0] "Verifica que este valor tiene por lo menos %(limit_value)d carácter. (Tiene %(show_value)d).)" +#~ msgstr[1] "Verifica que este valor tiene por lo menos %(limit_value)d caracteres. (Tiene %(show_value)d).)" -#: venv/lib/python3.8/site-packages/django/core/validators.py:389 -#, python-format -msgid "Ensure that there are no more than %(max)s digit in total." -msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "Verifica que no hay más que %(max)s digito en total." -msgstr[1] "Verifica que no hay más que %(max)s digitos en total." +#~ msgid "Ensure this value has at most %(limit_value)d character (it has %(show_value)d)." +#~ msgid_plural "Ensure this value has at most %(limit_value)d characters (it has %(show_value)d)." +#~ msgstr[0] "Verifica que este valor tiene a lo sumo %(limit_value)d carácter. (Tiene %(show_value)d).)" +#~ msgstr[1] "Verifica que este valor tiene a lo sumo %(limit_value)d caracteres. (Tiene %(show_value)d).)" + +#~ msgid "Enter a number." +#~ msgstr "Ingrese un número." + +#~ msgid "Ensure that there are no more than %(max)s digit in total." +#~ msgid_plural "Ensure that there are no more than %(max)s digits in total." +#~ msgstr[0] "Verifica que no hay más que %(max)s digito en total." +#~ msgstr[1] "Verifica que no hay más que %(max)s digitos en total." -#: venv/lib/python3.8/site-packages/django/core/validators.py:394 -#, python-format # is -msgid "Ensure that there are no more than %(max)s decimal place." -msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "Verifica que no hay más que %(max)s cifra decimal." -msgstr[1] "Verifica que no hay más que %(max)s cifras decimales." - -#: venv/lib/python3.8/site-packages/django/core/validators.py:399 -#, python-format -msgid "Ensure that there are no more than %(max)s digit before the decimal point." -msgid_plural "Ensure that there are no more than %(max)s digits before the decimal point." -msgstr[0] "Verifica que no hay más que %(max)s digito antes de la coma decimal." -msgstr[1] "Verifica que no hay más que %(max)s digitos antes de la coma decimal." - -#: venv/lib/python3.8/site-packages/django/core/validators.py:461 -#, python-format -msgid "File extension “%(extension)s” is not allowed. Allowed extensions are: %(allowed_extensions)s." -msgstr "No se permite la extensión de archivo “%(extension)s”. Extensiones permitidas son: %(allowed_extensions)s." - -#: venv/lib/python3.8/site-packages/django/core/validators.py:513 -msgid "Null characters are not allowed." -msgstr "No se permiten caracteres nulos" - -#: venv/lib/python3.8/site-packages/django/db/models/base.py:1190 -#: venv/lib/python3.8/site-packages/django/forms/models.py:760 -msgid "and" -msgstr "y" - -#: venv/lib/python3.8/site-packages/django/db/models/base.py:1192 -msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "Ya existe %(model_name)s con este %(field_labels)s." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:100 -msgid "Value %(value)r is not a valid choice." -msgstr "El valor %(value)s no es una opción válida." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:101 -msgid "This field cannot be null." -msgstr "Este campo no puede ser nulo." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:102 -msgid "This field cannot be blank." -msgstr "Este campo no puede ser vacio." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:103 -msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "Ya existe %(model_name)s con este %(field_labels)s." - -#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. -#. Eg: "Title must be unique for pub_date year" -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:107 -#, python-format -msgid "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." -msgstr "%(field_label)s deben ser unicos por %(date_field_label)s %(lookup_type)s." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:126 -#, python-format -msgid "Field of type: %(field_type)s" -msgstr "Campo de tipo: %(field_type)s" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:939 -#, python-format -msgid "“%(value)s” value must be either True or False." -msgstr "“%(value)s” valor debe ser o verdadero o falso." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:940 -#, python-format -msgid "“%(value)s” value must be either True, False, or None." -msgstr "%(value)s” valor debe ser o True, False, o None." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:942 -msgid "Boolean (Either True or False)" -msgstr "Booleano (O True O False)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:983 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "Cadena (máximo de %(max_length)s caracteres)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1047 -msgid "Comma-separated integers" -msgstr "Enteros separados por comas" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1096 -#, python-format -msgid "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD format." -msgstr "“%(value)s” valor tiene un formato de fecha inválido. Hay que estar de formato YYYY-MM-DD." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1098 -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1241 -#, python-format -msgid "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid date." -msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD) pero la fecha es invalida." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1101 -msgid "Date (without time)" -msgstr "Fecha (sin la hora)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1239 -#, python-format -msgid "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format." -msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1243 -#, python-format -msgid "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) but it is an invalid date/time." -msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) pero es una fecha/hora invalida." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1247 -msgid "Date (with time)" -msgstr "Fecha (con la hora)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1395 -msgid "“%(value)s” value must be a decimal number." -msgstr "El valor de “%(value)s” debe ser un número decimal." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1397 -msgid "Decimal number" -msgstr "Número decimal" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1536 -#, python-format -msgid "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[.uuuuuu] format." -msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato [DD] [[HH:]MM:]ss[.uuuuuu]." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1539 -msgid "Duration" -msgstr "Duración" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1589 -msgid "Email address" -msgstr "Dirección de correo electrónico" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1612 -msgid "File path" -msgstr "Ruta de archivo" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1678 -msgid "“%(value)s” value must be a float." -msgstr "%(value)s no es un usuario válido" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1680 -msgid "Floating point number" -msgstr "Número de coma flotante" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1718 -#, python-format -msgid "“%(value)s” value must be an integer." -msgstr "“%(value)s” valor debe ser un entero." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1720 -msgid "Integer" -msgstr "Entero" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1803 -msgid "Big (8 byte) integer" -msgstr "Entero grande (8 byte)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1819 -msgid "IPv4 address" -msgstr "Dirección IPv4" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1850 -msgid "IP address" -msgstr "Dirección IP" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1930 -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1931 -#, python-format -msgid "“%(value)s” value must be either None, True or False." -msgstr "Valor “%(value)s” debe ser o None, True, o False." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1933 -msgid "Boolean (Either True, False or None)" -msgstr "Booleano (O True, Falso, o None)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1976 -msgid "Positive big integer" -msgstr "Entero positivo grande" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1989 -msgid "Positive integer" -msgstr "Entero positivo" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2002 -msgid "Positive small integer" -msgstr "Entero positivo pequeño " - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2016 -#, python-format -msgid "Slug (up to %(max_length)s)" -msgstr "Slug (máximo de %(max_length)s)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2048 -msgid "Small integer" -msgstr "Entero pequeño" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2055 -msgid "Text" -msgstr "Texto" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2083 -#, python-format -msgid "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] format." -msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato HH:MM[:ss[.uuuuuu]]." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2085 -#, python-format -msgid "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an invalid time." -msgstr "“%(value)s” valor tiene el formato correcto (HH:MM[:ss[.uuuuuu]]) pero es una hora invalida." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2088 -msgid "Time" -msgstr "Tiempo" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2214 -msgid "URL" -msgstr "URL" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2236 -msgid "Raw binary data" -msgstr "Datos binarios sin procesar" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2301 -msgid "“%(value)s” is not a valid UUID." -msgstr "%(value)s no es una UUID válida." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:2303 -msgid "Universally unique identifier" -msgstr "Identificador universalmente único" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/files.py:231 -msgid "File" -msgstr "Archivo" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/files.py:379 -msgid "Image" -msgstr "Imágen" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:18 -msgid "A JSON object" -msgstr "Un objeto JSON" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/json.py:20 -msgid "Value must be valid JSON." -msgstr "Valor debe ser JSON válido." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:790 -#, python-format -msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "%(model)s instancia con %(field)s %(value)r no existe." - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:792 -msgid "Foreign Key (type determined by related field)" -msgstr "Clave externa (tipo determinado por campo relacionado)" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1045 -msgid "One-to-one relationship" -msgstr "Relación uno-a-uno" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1099 -msgid "%(from)s-%(to)s relationship" -msgstr "relación %(from)s-%(to)s" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1100 -msgid "%(from)s-%(to)s relationships" -msgstr "relaciones %(from)s-%(to)s" - -#: venv/lib/python3.8/site-packages/django/db/models/fields/related.py:1142 -msgid "Many-to-many relationship" -msgstr "Relaciones mucho-a-mucho" - -#. Translators: If found as last label character, these punctuation -#. characters will prevent the default label_suffix to be appended to the label -#: venv/lib/python3.8/site-packages/django/forms/boundfield.py:150 -msgid ":?.!" -msgstr "" - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:54 -msgid "This field is required." -msgstr "Este campo es requerido." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:247 -msgid "Enter a whole number." -msgstr "Ingrese un número entero." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:398 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:1139 -msgid "Enter a valid date." -msgstr "Ingrese una fecha válida." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:422 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:1140 -msgid "Enter a valid time." -msgstr "Ingrese una hora válida." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:450 -msgid "Enter a valid date/time." -msgstr "Ingrese una fecha/hora válida." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:484 -msgid "Enter a valid duration." -msgstr "Ingrese una duración válida." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:485 -#, python-brace-format -msgid "The number of days must be between {min_days} and {max_days}." -msgstr "El número de dias debe ser entre {min_days} y {max_days}." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:545 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "No se aceptó ningun archivo. Verfica el tipo de codificación en el formulario." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:546 -msgid "No file was submitted." -msgstr "No se aceptó ningun archivo." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:547 -msgid "The submitted file is empty." -msgstr "El archivo enviado está vacio." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:549 -#, python-format -msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." -msgid_plural "Ensure this filename has at most %(max)d characters (it has %(length)d)." -msgstr[0] "Verifica que este nombre de archivo no tiene más que %(max)d carácter. (Tiene %(length)d)." -msgstr[1] "Verifica que este nombre de archivo no tiene más que %(max)d caracteres. (Tiene %(length)d)." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:552 -msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "Por favor, o envia un archivo o marca la casilla vacia, no los dos." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:613 -msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." -msgstr "Subir una imagen válida. El archivo que subiste o no fue imagen o fue corrupto." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:775 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:865 -#: venv/lib/python3.8/site-packages/django/forms/models.py:1296 -#, python-format -msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "Selecciona una opción válida. %(value)s no es una de las opciones disponibles." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:866 -#: venv/lib/python3.8/site-packages/django/forms/fields.py:981 -#: venv/lib/python3.8/site-packages/django/forms/models.py:1295 -msgid "Enter a list of values." -msgstr "Ingrese una lista de valores." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:982 -msgid "Enter a complete value." -msgstr "Ingresa un valor completo." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:1198 -msgid "Enter a valid UUID." -msgstr "Ingrese una UUID válida." - -#: venv/lib/python3.8/site-packages/django/forms/fields.py:1228 -msgid "Enter a valid JSON." -msgstr "Ingrese una JSON válida." - -#. Translators: This is the default suffix added to form field labels -#: venv/lib/python3.8/site-packages/django/forms/forms.py:78 -msgid ":" -msgstr ":" - -#: venv/lib/python3.8/site-packages/django/forms/forms.py:205 -#, python-format -msgid "(Hidden field %(name)s) %(error)s" -msgstr "(Campo oculto %(name)s) %(error)s" - -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:93 -msgid "ManagementForm data is missing or has been tampered with" -msgstr "Datos de ManagementForm está ausento o ha sido corrompido" - -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:345 -#, python-format -msgid "Please submit %d or fewer forms." -msgid_plural "Please submit %d or fewer forms." -msgstr[0] "Por favor, enviar %d o menos formularios." -msgstr[1] "Por favor, enviar %d o menos formularios." - -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:352 -#, python-format -msgid "Please submit %d or more forms." -msgid_plural "Please submit %d or more forms." -msgstr[0] "Por favor, enviar %d o más formularios." -msgstr[1] "Por favor, enviar %d o más formularios." - -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:379 -#: venv/lib/python3.8/site-packages/django/forms/formsets.py:386 -#, fuzzy +#~ msgid "Ensure that there are no more than %(max)s decimal place." +#~ msgid_plural "Ensure that there are no more than %(max)s decimal places." +#~ msgstr[0] "Verifica que no hay más que %(max)s cifra decimal." +#~ msgstr[1] "Verifica que no hay más que %(max)s cifras decimales." + +#~ msgid "Ensure that there are no more than %(max)s digit before the decimal point." +#~ msgid_plural "Ensure that there are no more than %(max)s digits before the decimal point." +#~ msgstr[0] "Verifica que no hay más que %(max)s digito antes de la coma decimal." +#~ msgstr[1] "Verifica que no hay más que %(max)s digitos antes de la coma decimal." + +#~ msgid "File extension “%(extension)s” is not allowed. Allowed extensions are: %(allowed_extensions)s." +#~ msgstr "No se permite la extensión de archivo “%(extension)s”. Extensiones permitidas son: %(allowed_extensions)s." + +#~ msgid "Null characters are not allowed." +#~ msgstr "No se permiten caracteres nulos" + +#~ msgid "and" +#~ msgstr "y" + +#~ msgid "%(model_name)s with this %(field_labels)s already exists." +#~ msgstr "Ya existe %(model_name)s con este %(field_labels)s." + +#~ msgid "Value %(value)r is not a valid choice." +#~ msgstr "El valor %(value)s no es una opción válida." + +#~ msgid "This field cannot be null." +#~ msgstr "Este campo no puede ser nulo." + +#~ msgid "This field cannot be blank." +#~ msgstr "Este campo no puede ser vacio." + +#~ msgid "%(model_name)s with this %(field_label)s already exists." +#~ msgstr "Ya existe %(model_name)s con este %(field_labels)s." + +#~ msgid "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +#~ msgstr "%(field_label)s deben ser unicos por %(date_field_label)s %(lookup_type)s." + +#~ msgid "Field of type: %(field_type)s" +#~ msgstr "Campo de tipo: %(field_type)s" + +#~ msgid "“%(value)s” value must be either True or False." +#~ msgstr "“%(value)s” valor debe ser o verdadero o falso." + +#~ msgid "“%(value)s” value must be either True, False, or None." +#~ msgstr "%(value)s” valor debe ser o True, False, o None." + +#~ msgid "Boolean (Either True or False)" +#~ msgstr "Booleano (O True O False)" + +#~ msgid "String (up to %(max_length)s)" +#~ msgstr "Cadena (máximo de %(max_length)s caracteres)" + +#~ msgid "Comma-separated integers" +#~ msgstr "Enteros separados por comas" + +#~ msgid "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD format." +#~ msgstr "“%(value)s” valor tiene un formato de fecha inválido. Hay que estar de formato YYYY-MM-DD." + +#~ msgid "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid date." +#~ msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD) pero la fecha es invalida." + +#~ msgid "Date (without time)" +#~ msgstr "Fecha (sin la hora)" + +#~ msgid "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format." +#~ msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#~ msgid "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) but it is an invalid date/time." +#~ msgstr "“%(value)s” valor tiene el formato correcto (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) pero es una fecha/hora invalida." + +#~ msgid "Date (with time)" +#~ msgstr "Fecha (con la hora)" + +#~ msgid "“%(value)s” value must be a decimal number." +#~ msgstr "El valor de “%(value)s” debe ser un número decimal." + +#~ msgid "Decimal number" +#~ msgstr "Número decimal" + +#~ msgid "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[.uuuuuu] format." +#~ msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato [DD] [[HH:]MM:]ss[.uuuuuu]." + +#~ msgid "Duration" +#~ msgstr "Duración" + +#~ msgid "Email address" +#~ msgstr "Dirección de correo electrónico" + +#~ msgid "File path" +#~ msgstr "Ruta de archivo" + +#~ msgid "“%(value)s” value must be a float." +#~ msgstr "%(value)s no es un usuario válido" + +#~ msgid "Floating point number" +#~ msgstr "Número de coma flotante" + +#~ msgid "“%(value)s” value must be an integer." +#~ msgstr "“%(value)s” valor debe ser un entero." + +#~ msgid "Integer" +#~ msgstr "Entero" + +#~ msgid "Big (8 byte) integer" +#~ msgstr "Entero grande (8 byte)" + +#~ msgid "IPv4 address" +#~ msgstr "Dirección IPv4" + +#~ msgid "IP address" +#~ msgstr "Dirección IP" + +#~ msgid "“%(value)s” value must be either None, True or False." +#~ msgstr "Valor “%(value)s” debe ser o None, True, o False." + +#~ msgid "Boolean (Either True, False or None)" +#~ msgstr "Booleano (O True, Falso, o None)" + +#~ msgid "Positive big integer" +#~ msgstr "Entero positivo grande" + +#~ msgid "Positive integer" +#~ msgstr "Entero positivo" + +#~ msgid "Positive small integer" +#~ msgstr "Entero positivo pequeño " + +#~ msgid "Slug (up to %(max_length)s)" +#~ msgstr "Slug (máximo de %(max_length)s)" + +#~ msgid "Small integer" +#~ msgstr "Entero pequeño" + +#~ msgid "Text" +#~ msgstr "Texto" + +#~ msgid "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] format." +#~ msgstr "“%(value)s” valor tiene un formato invalido. Debe estar en formato HH:MM[:ss[.uuuuuu]]." + +#~ msgid "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an invalid time." +#~ msgstr "“%(value)s” valor tiene el formato correcto (HH:MM[:ss[.uuuuuu]]) pero es una hora invalida." + +#~ msgid "Time" +#~ msgstr "Tiempo" + +#~ msgid "URL" +#~ msgstr "URL" + +#~ msgid "Raw binary data" +#~ msgstr "Datos binarios sin procesar" + +#~ msgid "“%(value)s” is not a valid UUID." +#~ msgstr "%(value)s no es una UUID válida." + +#~ msgid "Universally unique identifier" +#~ msgstr "Identificador universalmente único" + +#~ msgid "File" +#~ msgstr "Archivo" + +#~ msgid "Image" +#~ msgstr "Imágen" + +#~ msgid "A JSON object" +#~ msgstr "Un objeto JSON" + +#~ msgid "Value must be valid JSON." +#~ msgstr "Valor debe ser JSON válido." + +#~ msgid "%(model)s instance with %(field)s %(value)r does not exist." +#~ msgstr "%(model)s instancia con %(field)s %(value)r no existe." + +#~ msgid "Foreign Key (type determined by related field)" +#~ msgstr "Clave externa (tipo determinado por campo relacionado)" + +#~ msgid "One-to-one relationship" +#~ msgstr "Relación uno-a-uno" + +#~ msgid "%(from)s-%(to)s relationship" +#~ msgstr "relación %(from)s-%(to)s" + +#~ msgid "%(from)s-%(to)s relationships" +#~ msgstr "relaciones %(from)s-%(to)s" + +#~ msgid "Many-to-many relationship" +#~ msgstr "Relaciones mucho-a-mucho" + +#~ msgid "This field is required." +#~ msgstr "Este campo es requerido." + +#~ msgid "Enter a whole number." +#~ msgstr "Ingrese un número entero." + +#~ msgid "Enter a valid date." +#~ msgstr "Ingrese una fecha válida." + +#~ msgid "Enter a valid time." +#~ msgstr "Ingrese una hora válida." + +#~ msgid "Enter a valid date/time." +#~ msgstr "Ingrese una fecha/hora válida." + +#~ msgid "Enter a valid duration." +#~ msgstr "Ingrese una duración válida." + +#~ msgid "The number of days must be between {min_days} and {max_days}." +#~ msgstr "El número de dias debe ser entre {min_days} y {max_days}." + +#~ msgid "No file was submitted. Check the encoding type on the form." +#~ msgstr "No se aceptó ningun archivo. Verfica el tipo de codificación en el formulario." + +#~ msgid "No file was submitted." +#~ msgstr "No se aceptó ningun archivo." + +#~ msgid "The submitted file is empty." +#~ msgstr "El archivo enviado está vacio." + +#~ msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +#~ msgid_plural "Ensure this filename has at most %(max)d characters (it has %(length)d)." +#~ msgstr[0] "Verifica que este nombre de archivo no tiene más que %(max)d carácter. (Tiene %(length)d)." +#~ msgstr[1] "Verifica que este nombre de archivo no tiene más que %(max)d caracteres. (Tiene %(length)d)." + +#~ msgid "Please either submit a file or check the clear checkbox, not both." +#~ msgstr "Por favor, o envia un archivo o marca la casilla vacia, no los dos." + +#~ msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +#~ msgstr "Subir una imagen válida. El archivo que subiste o no fue imagen o fue corrupto." + +#~ msgid "Select a valid choice. %(value)s is not one of the available choices." +#~ msgstr "Selecciona una opción válida. %(value)s no es una de las opciones disponibles." + +#~ msgid "Enter a list of values." +#~ msgstr "Ingrese una lista de valores." + +#~ msgid "Enter a complete value." +#~ msgstr "Ingresa un valor completo." + +#~ msgid "Enter a valid UUID." +#~ msgstr "Ingrese una UUID válida." + +#~ msgid "Enter a valid JSON." +#~ msgstr "Ingrese una JSON válida." + +#~ msgid ":" +#~ msgstr ":" + +#~ msgid "(Hidden field %(name)s) %(error)s" +#~ msgstr "(Campo oculto %(name)s) %(error)s" + +#~ msgid "ManagementForm data is missing or has been tampered with" +#~ msgstr "Datos de ManagementForm está ausento o ha sido corrompido" + +#~ msgid "Please submit %d or fewer forms." +#~ msgid_plural "Please submit %d or fewer forms." +#~ msgstr[0] "Por favor, enviar %d o menos formularios." +#~ msgstr[1] "Por favor, enviar %d o menos formularios." + +#~ msgid "Please submit %d or more forms." +#~ msgid_plural "Please submit %d or more forms." +#~ msgstr[0] "Por favor, enviar %d o más formularios." +#~ msgstr[1] "Por favor, enviar %d o más formularios." + # TODO cc @mouse is this a verb or noun -msgid "Order" -msgstr "Pedir" # if verb +#, fuzzy +#~ msgid "Order" +#~ msgstr "Pedir" + +# if verb # msgstr "Pedido" # if noun +#~ msgid "Please correct the duplicate data for %(field)s." +#~ msgstr "Por favor corrige los datos duplicados en %(field)s." + +#~ msgid "Please correct the duplicate data for %(field)s, which must be unique." +#~ msgstr "Por favor corrige los datos duplicados en %(field)s, los cuales deben ser unicos." + +#~ msgid "Please correct the duplicate data for %(field_name)s which must be unique for the %(lookup)s in %(date_field)s." +#~ msgstr "Por favor corrige los datos duplicados en %(field_name)s los cuales deben ser unicos por el %(lookup)s en %(date_field)s." + +#~ msgid "Please correct the duplicate values below." +#~ msgstr "Por favor corrige los valores duplicados a continuación." + +#~ msgid "The inline value did not match the parent instance." +#~ msgstr "El valor en línea no empareja la instancia progenitor." + +#~ msgid "Select a valid choice. That choice is not one of the available choices." +#~ msgstr "Selecciona una opción válida. Esa opción no es una de las opciones disponibles." + +#~ msgid "“%(pk)s” is not a valid value." +#~ msgstr "“%(pk)s” no es un valor válido." + +#~ msgid "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it may be ambiguous or it may not exist." +#~ msgstr "%(datetime)s no se pudo interpretar en la zona horaria %(current_timezone)s; puede ser ambiguo o puede que no exista." + +#~ msgid "Clear" +#~ msgstr "Borrar" + +#~ msgid "Currently" +#~ msgstr "Actualmente" + +#~ msgid "Change" +#~ msgstr "Cambiar" + +#~ msgid "Unknown" +#~ msgstr "Desconocido" + +#~ msgid "Yes" +#~ msgstr "Sí" + +#~ msgid "No" +#~ msgstr "No" + +#~ msgid "yes,no,maybe" +#~ msgstr "sí,no,quizás" + +#~ msgid "%(size)d byte" +#~ msgid_plural "%(size)d bytes" +#~ msgstr[0] "%(size)d byte" +#~ msgstr[1] "%(size)d bytes" + +#~ msgid "%s KB" +#~ msgstr "%s KB" + +#~ msgid "%s MB" +#~ msgstr "%s MB" + +#~ msgid "%s GB" +#~ msgstr "%s GB" + +#~ msgid "%s TB" +#~ msgstr "%s TB" + +#~ msgid "%s PB" +#~ msgstr "%s PB" + +#~ msgid "p.m." +#~ msgstr "p.m." + +#~ msgid "a.m." +#~ msgstr "a.m." + +#~ msgid "PM" +#~ msgstr "PM" + +#~ msgid "AM" +#~ msgstr "AM" + +#~ msgid "midnight" +#~ msgstr "medianoche" + +#~ msgid "noon" +#~ msgstr "mediodia" + +#~ msgid "Monday" +#~ msgstr "Lunes" + +#~ msgid "Tuesday" +#~ msgstr "Martes" + +#~ msgid "Wednesday" +#~ msgstr "Miercoles" + +#~ msgid "Thursday" +#~ msgstr "Jueves" + +#~ msgid "Friday" +#~ msgstr "Viernes" + +#~ msgid "Saturday" +#~ msgstr "Sábado" + +#~ msgid "Sunday" +#~ msgstr "Domino" + +#~ msgid "Mon" +#~ msgstr "Lun" + +#~ msgid "Tue" +#~ msgstr "Mar" + +#~ msgid "Wed" +#~ msgstr "Mie" + +#~ msgid "Thu" +#~ msgstr "Jue" + +#~ msgid "Fri" +#~ msgstr "Vie" + +#~ msgid "Sat" +#~ msgstr "Sáb" + +#~ msgid "Sun" +#~ msgstr "Dom" + +#~ msgid "January" +#~ msgstr "Enero" + +#~ msgid "February" +#~ msgstr "Febrero" + +#~ msgid "March" +#~ msgstr "Marzo" + +#~ msgid "April" +#~ msgstr "Abril" + +#~ msgid "May" +#~ msgstr "Mayo" + +#~ msgid "June" +#~ msgstr "Junio" + +#~ msgid "July" +#~ msgstr "Julio" + +#~ msgid "August" +#~ msgstr "Agosto" + +#~ msgid "September" +#~ msgstr "Septiembre" + +#~ msgid "October" +#~ msgstr "Octubre" + +#~ msgid "November" +#~ msgstr "Noviembre" + +#~ msgid "December" +#~ msgstr "Diciembre" + +#~ msgid "jan" +#~ msgstr "ene" + +#~ msgid "feb" +#~ msgstr "feb" + +#~ msgid "mar" +#~ msgstr "mar" + +#~ msgid "apr" +#~ msgstr "abr" + +#~ msgid "may" +#~ msgstr "may" + +#~ msgid "jun" +#~ msgstr "jun" + +#~ msgid "jul" +#~ msgstr "jul" + +#~ msgid "aug" +#~ msgstr "ago" + +#~ msgid "sep" +#~ msgstr "sep" + +#~ msgid "oct" +#~ msgstr "oct" + +#~ msgid "nov" +#~ msgstr "nov" + +#~ msgid "dec" +#~ msgstr "dic" + +#~ msgctxt "abbrev. month" +#~ msgid "Jan." +#~ msgstr "en." + +#~ msgctxt "abbrev. month" +#~ msgid "Feb." +#~ msgstr "feb." + +#~ msgctxt "abbrev. month" +#~ msgid "March" +#~ msgstr "mzo." + +#~ msgctxt "abbrev. month" +#~ msgid "April" +#~ msgstr "abr." + +#~ msgctxt "abbrev. month" +#~ msgid "May" +#~ msgstr "my." + +#~ msgctxt "abbrev. month" +#~ msgid "June" +#~ msgstr "jun." + +#~ msgctxt "abbrev. month" +#~ msgid "July" +#~ msgstr "jul." + +#~ msgctxt "abbrev. month" +#~ msgid "Aug." +#~ msgstr "agto." + +#~ msgctxt "abbrev. month" +#~ msgid "Sept." +#~ msgstr "set." + +#~ msgctxt "abbrev. month" +#~ msgid "Oct." +#~ msgstr "oct." + +#~ msgctxt "abbrev. month" +#~ msgid "Nov." +#~ msgstr "nov." + +#~ msgctxt "abbrev. month" +#~ msgid "Dec." +#~ msgstr "dic." + +#~ msgctxt "alt. month" +#~ msgid "January" +#~ msgstr "Enero" + +#~ msgctxt "alt. month" +#~ msgid "February" +#~ msgstr "Febrero" + +#~ msgctxt "alt. month" +#~ msgid "March" +#~ msgstr "Marzo" + +#~ msgctxt "alt. month" +#~ msgid "April" +#~ msgstr "Abril" + +#~ msgctxt "alt. month" +#~ msgid "May" +#~ msgstr "Mayo" + +#~ msgctxt "alt. month" +#~ msgid "June" +#~ msgstr "Junio" + +#~ msgctxt "alt. month" +#~ msgid "July" +#~ msgstr "Julio" + +#~ msgctxt "alt. month" +#~ msgid "August" +#~ msgstr "Agosto" + +#~ msgctxt "alt. month" +#~ msgid "September" +#~ msgstr "Septiembre" + +#~ msgctxt "alt. month" +#~ msgid "October" +#~ msgstr "Octubre" + +#~ msgctxt "alt. month" +#~ msgid "November" +#~ msgstr "Noviembre" + +#~ msgctxt "alt. month" +#~ msgid "December" +#~ msgstr "Diciembre" + +#~ msgid "This is not a valid IPv6 address." +#~ msgstr "Esta no es una dirección IPv6 válida." + +#~ msgctxt "String to return when truncating text" +#~ msgid "%(truncated_text)s…" +#~ msgstr "%(truncated_text)s…" + +#~ msgid "or" +#~ msgstr "o" + +#~ msgid ", " +#~ msgstr ", " + +#~ msgid "%d year" +#~ msgid_plural "%d years" +#~ msgstr[0] "%d año" +#~ msgstr[1] "%d años" + +#~ msgid "%d month" +#~ msgid_plural "%d months" +#~ msgstr[0] "%d mes" +#~ msgstr[1] "%d meses" + +#~ msgid "%d week" +#~ msgid_plural "%d weeks" +#~ msgstr[0] "%d semana" +#~ msgstr[1] "%d semanas" + +#~ msgid "%d day" +#~ msgid_plural "%d days" +#~ msgstr[0] "%d día" +#~ msgstr[1] "%d días" + +#~ msgid "%d hour" +#~ msgid_plural "%d hours" +#~ msgstr[0] "%d hora" +#~ msgstr[1] "%d horas" + +#~ msgid "%d minute" +#~ msgid_plural "%d minutes" +#~ msgstr[0] "%d minuto" +#~ msgstr[1] "%d minutos" + +#~ msgid "Forbidden" +#~ msgstr "Prohibido" + +#~ msgid "CSRF verification failed. Request aborted." +#~ msgstr "Se falló la verificación CSRF. Se abortó la solicitud." + +#~ msgid "You are seeing this message because this HTTPS site requires a “Referer header” to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties." +#~ msgstr "Estás viendo este mensaje porque este sitio HTTPS requiere que tu navegador Web envie un “Referer header”, pero no se la envió. Esta cabecedera se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." + +#~ msgid "If you have configured your browser to disable “Referer” headers, please re-enable them, at least for this site, or for HTTPS connections, or for “same-origin” requests." +#~ msgstr "Si has configurado su navegador para deshabilitar las cabecederas “Referer”, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " + +#~ msgid "If you are using the tag or including the “Referrer-Policy: no-referrer” header, please remove them. The CSRF protection requires the “Referer” header to do strict referer checking. If you’re concerned about privacy, use alternatives like for links to third-party sites." +#~ msgstr "Si estás usando la eqtigueta o estás incluyendo la cabecedera “Referrer-Policy: no-referrer”, quitalas por favor. La protección CSRF require la cabecedera “Referer” para hacer verficación “strict referer“. Si te preocupa la privacidad, utiliza alternativas como para sitios de terceros." + +#~ msgid "You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties." +#~ msgstr "Estás viendo este mensaje porque este sitio requiere un cookie CSRF cuando se envie formularios. Este cookie se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." + +#~ msgid "If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for “same-origin” requests." +#~ msgstr "Si has configurado su navegador para deshabilitar los cookies, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " + +#~ msgid "More information is available with DEBUG=True." +#~ msgstr "Más información es disponible con DEBUG=True." + +#~ msgid "No year specified" +#~ msgstr "Ningun año fue especificado" + +#~ msgid "Date out of range" +#~ msgstr "Fecha fuera de rango" + +#~ msgid "No month specified" +#~ msgstr "Ningun mes fue especificado" + +#~ msgid "No day specified" +#~ msgstr "Ningun día fue especificado" + +#~ msgid "No week specified" +#~ msgstr "Ninguna semana fue especificado" + +#~ msgid "No %(verbose_name_plural)s available" +#~ msgstr "No %(verbose_name_plural)s disponible" + +#~ msgid "Future %(verbose_name_plural)s not available because %(class_name)s.allow_future is False." +#~ msgstr "%(verbose_name_plural)s del futuro no está disponible porque %(class_name)s.allow_future es False." + +#~ msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +#~ msgstr "Cadena de fecha invalida “%(datestr)s” dado el formato “%(format)s”" + +#~ msgid "No %(verbose_name)s found matching the query" +#~ msgstr "No se encontró ningún %(verbose_name)s correspondiente a la búsqueda" + +#~ msgid "Page is not “last”, nor can it be converted to an int." +#~ msgstr "Página no es “last”, ni puede ser convertido en un int." + +#~ msgid "Invalid page (%(page_number)s): %(message)s" +#~ msgstr "Página invalida (%(page_number)s): %(message)s" + +#~ msgid "Empty list and “%(class_name)s.allow_empty” is False." +#~ msgstr "Lista vacia y “%(class_name)s.allow_empty” es False." + +#~ msgid "Directory indexes are not allowed here." +#~ msgstr "Indices directorios no se permiten aquí." + +#~ msgid "“%(path)s” does not exist" +#~ msgstr "“%(path)s” no existe" + +#~ msgid "Index of %(directory)s" +#~ msgstr "Indice de %(directory)s" + +#~ msgid "Django: the Web framework for perfectionists with deadlines." +#~ msgstr "Django: el estructura Web para perfeccionistas con fechas límites." + +#~ msgid "View release notes for Django %(version)s" +#~ msgstr "Ver notas de lanzamiento por Django %(version)s" + +#~ msgid "The install worked successfully! Congratulations!" +#~ msgstr "¡La instalación fue exitoso! ¡Felicidades!" + +#~ msgid "You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs." +#~ msgstr "Estás viendo esta pagina porque DEBUG=True está en tu archivo de configuración y no has configurado ningún URL." + +#~ msgid "Django Documentation" +#~ msgstr "Documentación de Django" + +#~ msgid "Topics, references, & how-to’s" +#~ msgstr "Tópicos, referencias, & instrucciones paso-a-paso" + +#~ msgid "Tutorial: A Polling App" +#~ msgstr "Tutorial: Una aplicación polling" + +#~ msgid "Get started with Django" +#~ msgstr "Empezar con Django" + +#~ msgid "Django Community" +#~ msgstr "Comunidad Django" + +#~ msgid "Connect, get help, or contribute" +#~ msgstr "Conectarse, encontrar ayuda, o contribuir" + +#~ msgid "Attempting to connect to qpid with SASL mechanism %s" +#~ msgstr "Intentando conectar con qpid con mecanismo SASL %s" + +#~ msgid "Connected to qpid with SASL mechanism %s" +#~ msgstr "Conectado con qpid con mecanismo SASL %s" + +#~ msgid "Unable to connect to qpid with SASL mechanism %s" +#~ msgstr "No se pudo conectar con qpid con mecanismo SASL %s" + +#~ msgid "1 second ago" +#~ msgstr "Hace 1 segundo" + +#~ msgid "1 minute ago" +#~ msgstr "Hace 1 minuto" + +#~ msgid "1 hour ago" +#~ msgstr "Hace 1 hora" + +#~ msgid "%(time)s" +#~ msgstr "%(time)s" + +#~ msgid "yesterday" +#~ msgstr "ayer" -#: venv/lib/python3.8/site-packages/django/forms/models.py:755 -#, python-format -msgid "Please correct the duplicate data for %(field)s." -msgstr "Por favor corrige los datos duplicados en %(field)s." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:759 -#, python-format -msgid "Please correct the duplicate data for %(field)s, which must be unique." -msgstr "Por favor corrige los datos duplicados en %(field)s, los cuales deben ser unicos." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:765 -#, python-format -msgid "Please correct the duplicate data for %(field_name)s which must be unique for the %(lookup)s in %(date_field)s." -msgstr "Por favor corrige los datos duplicados en %(field_name)s los cuales deben ser unicos por el %(lookup)s en %(date_field)s." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:774 -msgid "Please correct the duplicate values below." -msgstr "Por favor corrige los valores duplicados a continuación." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:1096 -msgid "The inline value did not match the parent instance." -msgstr "El valor en línea no empareja la instancia progenitor." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:1180 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "Selecciona una opción válida. Esa opción no es una de las opciones disponibles." - -#: venv/lib/python3.8/site-packages/django/forms/models.py:1298 -msgid "“%(pk)s” is not a valid value." -msgstr "“%(pk)s” no es un valor válido." - -#: venv/lib/python3.8/site-packages/django/forms/utils.py:167 -#, python-format -msgid "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it may be ambiguous or it may not exist." -msgstr "%(datetime)s no se pudo interpretar en la zona horaria %(current_timezone)s; puede ser ambiguo o puede que no exista." - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:398 -msgid "Clear" -msgstr "Borrar" - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:399 -msgid "Currently" -msgstr "Actualmente" - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:400 -msgid "Change" -msgstr "Cambiar" - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:709 -msgid "Unknown" -msgstr "Desconocido" - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:710 -msgid "Yes" -msgstr "Sí" - -#: venv/lib/python3.8/site-packages/django/forms/widgets.py:711 -msgid "No" -msgstr "No" - -#. Translators: Please do not add spaces around commas. -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:790 -msgid "yes,no,maybe" -msgstr "sí,no,quizás" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:819 -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:836 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "%(size)d byte" -msgstr[1] "%(size)d bytes" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:838 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:840 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:842 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:844 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: venv/lib/python3.8/site-packages/django/template/defaultfilters.py:846 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:65 -msgid "p.m." -msgstr "p.m." - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:66 -msgid "a.m." -msgstr "a.m." - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:71 -msgid "PM" -msgstr "PM" - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:72 -msgid "AM" -msgstr "AM" - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:149 -msgid "midnight" -msgstr "medianoche" - -#: venv/lib/python3.8/site-packages/django/utils/dateformat.py:151 -msgid "noon" -msgstr "mediodia" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:6 -#: venv/lib/python3.8/site-packages/tornado/locale.py:295 -msgid "Monday" -msgstr "Lunes" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:6 -#: venv/lib/python3.8/site-packages/tornado/locale.py:296 -msgid "Tuesday" -msgstr "Martes" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:6 -#: venv/lib/python3.8/site-packages/tornado/locale.py:297 -msgid "Wednesday" -msgstr "Miercoles" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:6 -#: venv/lib/python3.8/site-packages/tornado/locale.py:298 -msgid "Thursday" -msgstr "Jueves" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:6 -#: venv/lib/python3.8/site-packages/tornado/locale.py:299 -msgid "Friday" -msgstr "Viernes" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:7 -#: venv/lib/python3.8/site-packages/tornado/locale.py:300 -msgid "Saturday" -msgstr "Sábado" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:7 -#: venv/lib/python3.8/site-packages/tornado/locale.py:301 -msgid "Sunday" -msgstr "Domino" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:10 -msgid "Mon" -msgstr "Lun" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:10 -msgid "Tue" -msgstr "Mar" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:10 -msgid "Wed" -msgstr "Mie" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:10 -msgid "Thu" -msgstr "Jue" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:10 -msgid "Fri" -msgstr "Vie" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:11 -msgid "Sat" -msgstr "Sáb" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:11 -msgid "Sun" -msgstr "Dom" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:281 -msgid "January" -msgstr "Enero" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:282 -msgid "February" -msgstr "Febrero" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:283 -msgid "March" -msgstr "Marzo" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:284 -msgid "April" -msgstr "Abril" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:285 -msgid "May" -msgstr "Mayo" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:14 -#: venv/lib/python3.8/site-packages/tornado/locale.py:286 -msgid "June" -msgstr "Junio" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:15 -#: venv/lib/python3.8/site-packages/tornado/locale.py:287 -msgid "July" -msgstr "Julio" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:15 -#: venv/lib/python3.8/site-packages/tornado/locale.py:288 -msgid "August" -msgstr "Agosto" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:15 -#: venv/lib/python3.8/site-packages/tornado/locale.py:289 -msgid "September" -msgstr "Septiembre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:15 -#: venv/lib/python3.8/site-packages/tornado/locale.py:290 -msgid "October" -msgstr "Octubre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:15 -#: venv/lib/python3.8/site-packages/tornado/locale.py:291 -msgid "November" -msgstr "Noviembre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:16 -#: venv/lib/python3.8/site-packages/tornado/locale.py:292 -msgid "December" -msgstr "Diciembre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "jan" -msgstr "ene" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "feb" -msgstr "feb" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "mar" -msgstr "mar" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "apr" -msgstr "abr" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "may" -msgstr "may" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:19 -msgid "jun" -msgstr "jun" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "jul" -msgstr "jul" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "aug" -msgstr "ago" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "sep" -msgstr "sep" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "oct" -msgstr "oct" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "nov" -msgstr "nov" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:20 -msgid "dec" -msgstr "dic" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:23 -msgctxt "abbrev. month" -msgid "Jan." -msgstr "en." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:24 -msgctxt "abbrev. month" -msgid "Feb." -msgstr "feb." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:25 -msgctxt "abbrev. month" -msgid "March" -msgstr "mzo." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:26 -msgctxt "abbrev. month" -msgid "April" -msgstr "abr." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:27 -msgctxt "abbrev. month" -msgid "May" -msgstr "my." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:28 -msgctxt "abbrev. month" -msgid "June" -msgstr "jun." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:29 -msgctxt "abbrev. month" -msgid "July" -msgstr "jul." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:30 -msgctxt "abbrev. month" -msgid "Aug." -msgstr "agto." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:31 -msgctxt "abbrev. month" -msgid "Sept." -msgstr "set." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:32 -msgctxt "abbrev. month" -msgid "Oct." -msgstr "oct." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:33 -msgctxt "abbrev. month" -msgid "Nov." -msgstr "nov." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:34 -msgctxt "abbrev. month" -msgid "Dec." -msgstr "dic." - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:37 -msgctxt "alt. month" -msgid "January" -msgstr "Enero" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:38 -msgctxt "alt. month" -msgid "February" -msgstr "Febrero" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:39 -msgctxt "alt. month" -msgid "March" -msgstr "Marzo" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:40 -msgctxt "alt. month" -msgid "April" -msgstr "Abril" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:41 -msgctxt "alt. month" -msgid "May" -msgstr "Mayo" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:42 -msgctxt "alt. month" -msgid "June" -msgstr "Junio" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:43 -msgctxt "alt. month" -msgid "July" -msgstr "Julio" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:44 -msgctxt "alt. month" -msgid "August" -msgstr "Agosto" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:45 -msgctxt "alt. month" -msgid "September" -msgstr "Septiembre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:46 -msgctxt "alt. month" -msgid "October" -msgstr "Octubre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:47 -msgctxt "alt. month" -msgid "November" -msgstr "Noviembre" - -#: venv/lib/python3.8/site-packages/django/utils/dates.py:48 -msgctxt "alt. month" -msgid "December" -msgstr "Diciembre" - -#: venv/lib/python3.8/site-packages/django/utils/ipv6.py:8 -msgid "This is not a valid IPv6 address." -msgstr "Esta no es una dirección IPv6 válida." - -#: venv/lib/python3.8/site-packages/django/utils/text.py:70 -#, python-format -msgctxt "String to return when truncating text" -msgid "%(truncated_text)s…" -msgstr "%(truncated_text)s…" - -#: venv/lib/python3.8/site-packages/django/utils/text.py:236 -msgid "or" -msgstr "o" - -#. Translators: This string is used as a separator between list elements -#: venv/lib/python3.8/site-packages/django/utils/text.py:255 -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:83 -msgid ", " -msgstr ", " - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:9 -#, python-format -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "%d año" -msgstr[1] "%d años" - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:10 -#, python-format -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "%d mes" -msgstr[1] "%d meses" - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:11 -#, python-format -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "%d semana" -msgstr[1] "%d semanas" - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:12 -#, python-format -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "%d día" -msgstr[1] "%d días" - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:13 -#, python-format -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "%d hora" -msgstr[1] "%d horas" - -#: venv/lib/python3.8/site-packages/django/utils/timesince.py:14 -#, python-format -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%d minuto" -msgstr[1] "%d minutos" - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:110 -msgid "Forbidden" -msgstr "Prohibido" - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:111 -msgid "CSRF verification failed. Request aborted." -msgstr "Se falló la verificación CSRF. Se abortó la solicitud." - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:115 -msgid "You are seeing this message because this HTTPS site requires a “Referer header” to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties." -msgstr "Estás viendo este mensaje porque este sitio HTTPS requiere que tu navegador Web envie un “Referer header”, pero no se la envió. Esta cabecedera se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:120 -msgid "If you have configured your browser to disable “Referer” headers, please re-enable them, at least for this site, or for HTTPS connections, or for “same-origin” requests." -msgstr "Si has configurado su navegador para deshabilitar las cabecederas “Referer”, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:124 -msgid "If you are using the tag or including the “Referrer-Policy: no-referrer” header, please remove them. The CSRF protection requires the “Referer” header to do strict referer checking. If you’re concerned about privacy, use alternatives like for links to third-party sites." -msgstr "Si estás usando la eqtigueta o estás incluyendo la cabecedera “Referrer-Policy: no-referrer”, quitalas por favor. La protección CSRF require la cabecedera “Referer” para hacer verficación “strict referer“. Si te preocupa la privacidad, utiliza alternativas como para sitios de terceros." - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:132 -msgid "You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties." -msgstr "Estás viendo este mensaje porque este sitio requiere un cookie CSRF cuando se envie formularios. Este cookie se requiere por razones de seguridad, para asegurar que tu navegador no sea secuestrado por terceros." - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:137 -msgid "If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for “same-origin” requests." -msgstr "Si has configurado su navegador para deshabilitar los cookies, vuelva a habilitarlos, al menos para este sitio, o para conexiones HTTPS, o para solicitudes del “same-origin”. " - -#: venv/lib/python3.8/site-packages/django/views/csrf.py:142 -msgid "More information is available with DEBUG=True." -msgstr "Más información es disponible con DEBUG=True." - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:41 -msgid "No year specified" -msgstr "Ningun año fue especificado" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:61 -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:111 -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:208 -msgid "Date out of range" -msgstr "Fecha fuera de rango" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:90 -msgid "No month specified" -msgstr "Ningun mes fue especificado" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:142 -msgid "No day specified" -msgstr "Ningun día fue especificado" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:188 -msgid "No week specified" -msgstr "Ninguna semana fue especificado" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:338 -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:367 -#, python-format -msgid "No %(verbose_name_plural)s available" -msgstr "No %(verbose_name_plural)s disponible" - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:589 -#, python-format -msgid "Future %(verbose_name_plural)s not available because %(class_name)s.allow_future is False." -msgstr "%(verbose_name_plural)s del futuro no está disponible porque %(class_name)s.allow_future es False." - -#: venv/lib/python3.8/site-packages/django/views/generic/dates.py:623 -#, python-format -msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "Cadena de fecha invalida “%(datestr)s” dado el formato “%(format)s”" - -#: venv/lib/python3.8/site-packages/django/views/generic/detail.py:54 -msgid "No %(verbose_name)s found matching the query" -msgstr "No se encontró ningún %(verbose_name)s correspondiente a la búsqueda" - -#: venv/lib/python3.8/site-packages/django/views/generic/list.py:67 -msgid "Page is not “last”, nor can it be converted to an int." -msgstr "Página no es “last”, ni puede ser convertido en un int." - -#: venv/lib/python3.8/site-packages/django/views/generic/list.py:72 -#, python-format -msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "Página invalida (%(page_number)s): %(message)s" - -#: venv/lib/python3.8/site-packages/django/views/generic/list.py:154 -#, python-format -msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "Lista vacia y “%(class_name)s.allow_empty” es False." - -#: venv/lib/python3.8/site-packages/django/views/static.py:40 -msgid "Directory indexes are not allowed here." -msgstr "Indices directorios no se permiten aquí." - -#: venv/lib/python3.8/site-packages/django/views/static.py:42 -msgid "“%(path)s” does not exist" -msgstr "“%(path)s” no existe" - -#: venv/lib/python3.8/site-packages/django/views/static.py:80 -#, python-format -msgid "Index of %(directory)s" -msgstr "Indice de %(directory)s" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:7 -msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "Django: el estructura Web para perfeccionistas con fechas límites." - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:346 -#, python-format -msgid "View release notes for Django %(version)s" -msgstr "Ver notas de lanzamiento por Django %(version)s" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:368 -msgid "The install worked successfully! Congratulations!" -msgstr "¡La instalación fue exitoso! ¡Felicidades!" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:369 -#, python-format -msgid "You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs." -msgstr "Estás viendo esta pagina porque DEBUG=True está en tu archivo de configuración y no has configurado ningún URL." - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:384 -msgid "Django Documentation" -msgstr "Documentación de Django" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:385 -msgid "Topics, references, & how-to’s" -msgstr "Tópicos, referencias, & instrucciones paso-a-paso" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:396 -msgid "Tutorial: A Polling App" -msgstr "Tutorial: Una aplicación polling" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:397 -msgid "Get started with Django" -msgstr "Empezar con Django" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:408 -msgid "Django Community" -msgstr "Comunidad Django" - -#: venv/lib/python3.8/site-packages/django/views/templates/default_urlconf.html:409 -msgid "Connect, get help, or contribute" -msgstr "Conectarse, encontrar ayuda, o contribuir" - -#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1301 -#, python-format -msgid "Attempting to connect to qpid with SASL mechanism %s" -msgstr "Intentando conectar con qpid con mecanismo SASL %s" - -#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1306 -#, python-format -msgid "Connected to qpid with SASL mechanism %s" -msgstr "Conectado con qpid con mecanismo SASL %s" - -#: venv/lib/python3.8/site-packages/kombu/transport/qpid.py:1324 -#, python-format -msgid "Unable to connect to qpid with SASL mechanism %s" -msgstr "No se pudo conectar con qpid con mecanismo SASL %s" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:371 -msgid "1 second ago" -msgstr "Hace 1 segundo" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:377 -msgid "1 minute ago" -msgstr "Hace 1 minuto" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:382 -msgid "1 hour ago" -msgstr "Hace 1 hora" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:385 -#, python-format -msgid "%(time)s" -msgstr "%(time)s" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:387 -msgid "yesterday" -msgstr "ayer" - -#: venv/lib/python3.8/site-packages/tornado/locale.py:387 -#, python-format # TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock # a working clock is broken twice a day! -msgid "yesterday at %(time)s" -msgstr "ayer a las %(time)s" +#~ msgid "yesterday at %(time)s" +#~ msgstr "ayer a las %(time)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:389 -#, python-format -msgid "%(weekday)s" -msgstr "%(weekday)s" +#~ msgid "%(weekday)s" +#~ msgstr "%(weekday)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:389 -#, python-format # TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock # a working clock is broken twice a day! -msgid "%(weekday)s at %(time)s" -msgstr "%(weekday)s a las %(time)s" +#~ msgid "%(weekday)s at %(time)s" +#~ msgstr "%(weekday)s a las %(time)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:392 -#: venv/lib/python3.8/site-packages/tornado/locale.py:445 -#, python-format -msgid "%(month_name)s %(day)s" -msgstr "%(day)s %(month_name)s" +#~ msgid "%(month_name)s %(day)s" +#~ msgstr "%(day)s %(month_name)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:394 -#, python-format # TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock # a working clock is broken twice a day! -msgid "%(month_name)s %(day)s at %(time)s" -msgstr "%(day)s %(month_name)s a las %(time)s" +#~ msgid "%(month_name)s %(day)s at %(time)s" +#~ msgstr "%(day)s %(month_name)s a las %(time)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:399 -#, python-format -msgid "%(month_name)s %(day)s, %(year)s" -msgstr "%(day)s %(month_name)s, %(year)s" +#~ msgid "%(month_name)s %(day)s, %(year)s" +#~ msgstr "%(day)s %(month_name)s, %(year)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:401 -#, python-format # TODO cc @mouse this could be grammatically incorrect if the time said 1 o'clock # a working clock is broken twice a day! -msgid "%(month_name)s %(day)s, %(year)s at %(time)s" -msgstr "%(day)s %(month_name)s, %(year)s a las %(time)s" +#~ msgid "%(month_name)s %(day)s, %(year)s at %(time)s" +#~ msgstr "%(day)s %(month_name)s, %(year)s a las %(time)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:439 -#, python-format -msgid "%(weekday)s, %(month_name)s %(day)s" -msgstr "%(weekday)s, %(day)s %(month_name)s" +#~ msgid "%(weekday)s, %(month_name)s %(day)s" +#~ msgstr "%(weekday)s, %(day)s %(month_name)s" -#: venv/lib/python3.8/site-packages/tornado/locale.py:462 -#, python-format -msgid "%(commas)s and %(last)s" -msgstr "%(commas)s y %(last)s" +#~ msgid "%(commas)s and %(last)s" +#~ msgstr "%(commas)s y %(last)s" -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:68 -msgctxt "law" -msgid "right" -msgstr "justo" +#~ msgctxt "law" +#~ msgid "right" +#~ msgstr "justo" -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:69 -msgctxt "good" -msgid "right" -msgstr "correcto" +#~ msgctxt "good" +#~ msgid "right" +#~ msgstr "correcto" -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:71 -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:74 -msgctxt "organization" -msgid "club" -msgstr "club" +#~ msgctxt "organization" +#~ msgid "club" +#~ msgstr "club" -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:76 -#: venv/lib/python3.8/site-packages/tornado/test/locale_test.py:77 -msgctxt "stick" -msgid "club" -msgstr "garrote" +#~ msgctxt "stick" +#~ msgid "club" +#~ msgstr "garrote" #, fuzzy #~| msgid "Started" From 648b990aab4a940004c4f1c3cea687dd2609512a Mon Sep 17 00:00:00 2001 From: reese Date: Thu, 22 Apr 2021 11:37:18 -0500 Subject: [PATCH 084/109] realized Read was in the past tense lol --- locale/es/LC_MESSAGES/django.mo | Bin 42569 -> 42570 bytes locale/es/LC_MESSAGES/django.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index f0d87d7039ba2302eba8733872a4fa81b1cb94f5..e2498fda1420d94d06c0a145c3132227038091f7 100644 GIT binary patch delta 1843 zcmXZcdrVJZ9LMozB}K|Fmwu^S)=xot)> zWQ=9YTw0qATl_&AHa52v{gd(jIL}|N=X=h1p6~bhp68sW%|XwagKl&UbV7_V4aLUv z#s}!Z7VA6o692${71Jc&_w1$*E<48x{F#xWxp zv~VFBJ8(RPA2y~hPDeeMg_^h)2Vf2=!G0TGLKV`8D!AGD0sX{XsC7n_xQ<5^G_}Mr zCX~TKE>z%hOv11B!MG#t{o$yE$DnpN$Ho~rk~kY9uo&a95|!XKs-sU(8*D{&az3nev@5 zW)?2TnOKf~@|#u$=@@d7PYW|qmF8IwSWjUl*XvO`GUe_LV^KRwM0G3~^=hV}Ix!cc zG0VoesQCrx^k-1QUi)T`*mr=p#DQO^%Y9lnV+o{jy8m!Ue9 ziz;ldy??-7FRP&cTCmPO(15DE5l7;48@F5kpmq{k=_VM2+Q|ge>0X3dZyjo5J5m3a zgQyK%wcbW``cWnQ*Mjf4pq+H03J5*rCWyin#6C>LBHV~~aW}@CHfA!GU?M)obNCar z^U^B!^w*%yz#YuRkGKFcoilC$m8ipU164pf>W}sZ_h8srV>Y3Ky8aHm_yzqKL{@zr z0o43SxCGNsiH@Sq&Ra~z#A-fmbT%;1yW5OvQ9fp25oTZuYGUkpcj9(bf+|!Y7jZ1s zqgvmF^RNR~;j|0<8?X%3$xoPqsWty!kz;l;q#jx&@`&>@lK#Tk!Ur LT{rI+ACCP89%vy7 delta 1842 zcmXZcdrXf}9LMqFhbVMIDVj_BNh*XPTIRA?(TbT|=9aL9Ho45uv*ka!5V|O$NH!zO zZMH01W}?l8E&fQGY;0}|{ZqsH<2ir5&i8qqbH3m6J?Hmpd*ONZ!qeCv;S4gyJUD4g z05)SFwp%+fl=wT2!XbsmjKFa?9;c!orl97pK_AS1+K<8{9->0FLB>Tq85%p?Qn^WQ!t8n8;-yeI1VdN3GSjg`V_Un4pc|Jqw;#3 zQ^rhU;D?$Jhf1)}#>uD&nK%q{a4R0dSbU2C=yTc_e+)r&%8L_mI_iA}s=%!{9CL9p zI!75qGN{98_!O0>7nRsk>h63r1`@}iTA74Ov<$W53{1eisQC@3#CK3f*^0VD9jN(V zF_`?Omw`Iqd&aFe7FA&y>cb7lhh{sfGly^t=A&9zZmqHJub~RKi7MbB>dv&Gj-VSg zuMhpnZw8)q69uDoI2KhvtbLwlyK9z2Q2-HqyqHgyJ)Ozbt8{32We>slY z&~@uwRHq+T(tj=Zo(I}VFRB2a^KODbTtn=|L_C6<@Btpc&?;l*Vi8WoCs>0&P&+?W z?cV-c)E&5oyRaKmaHVs>EuaE*Ic}i}=t2FX_2WSta?zO0n2&niiJ|xzV{iaj_3Ma3 z&7Y0wn1o7Hg1S5Ja3)4y;uz7{$UtYe1=XTl%)ldDY*B zeHSL Date: Thu, 22 Apr 2021 18:16:00 -0700 Subject: [PATCH 085/109] Fixes duplicate boosts --- bookwyrm/models/activitypub_mixin.py | 6 +++++- bookwyrm/tests/views/test_interaction.py | 27 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 82a45ac86..2e248fbe3 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -204,7 +204,11 @@ class ObjectMixin(ActivitypubMixin): created = created or not bool(self.id) # first off, we want to save normally no matter what super().save(*args, **kwargs) - if not broadcast: + if ( + not broadcast + or hasattr(self, "status_type") + and self.status_type == "Announce" + ): return # this will work for objects owned by a user (lists, shelves) diff --git a/bookwyrm/tests/views/test_interaction.py b/bookwyrm/tests/views/test_interaction.py index 8d2c63ffc..f767edfaa 100644 --- a/bookwyrm/tests/views/test_interaction.py +++ b/bookwyrm/tests/views/test_interaction.py @@ -1,4 +1,5 @@ """ test for app action functionality """ +import json from unittest.mock import patch from django.test import TestCase from django.test.client import RequestFactory @@ -39,7 +40,7 @@ class InteractionViews(TestCase): parent_work=work, ) - def test_handle_favorite(self, _): + def test_favorite(self, _): """ create and broadcast faving a status """ view = views.Favorite.as_view() request = self.factory.post("") @@ -57,7 +58,7 @@ class InteractionViews(TestCase): self.assertEqual(notification.user, self.local_user) self.assertEqual(notification.related_user, self.remote_user) - def test_handle_unfavorite(self, _): + def test_unfavorite(self, _): """ unfav a status """ view = views.Unfavorite.as_view() request = self.factory.post("") @@ -74,7 +75,7 @@ class InteractionViews(TestCase): self.assertEqual(models.Favorite.objects.count(), 0) self.assertEqual(models.Notification.objects.count(), 0) - def test_handle_boost(self, _): + def test_boost(self, _): """ boost a status """ view = views.Boost.as_view() request = self.factory.post("") @@ -85,6 +86,7 @@ class InteractionViews(TestCase): view(request, status.id) boost = models.Boost.objects.get() + self.assertEqual(boost.boosted_status, status) self.assertEqual(boost.user, self.remote_user) self.assertEqual(boost.privacy, "public") @@ -95,7 +97,7 @@ class InteractionViews(TestCase): self.assertEqual(notification.related_user, self.remote_user) self.assertEqual(notification.related_status, status) - def test_handle_self_boost(self, _): + def test_self_boost(self, _): """ boost your own status """ view = views.Boost.as_view() request = self.factory.post("") @@ -103,7 +105,14 @@ class InteractionViews(TestCase): with patch("bookwyrm.activitystreams.ActivityStream.add_status"): status = models.Status.objects.create(user=self.local_user, content="hi") - view(request, status.id) + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.delay" + ) as broadcast_mock: + view(request, status.id) + + self.assertEqual(broadcast_mock.call_count, 1) + activity = json.loads(broadcast_mock.call_args[0][1]) + self.assertEqual(activity["type"], "Announce") boost = models.Boost.objects.get() self.assertEqual(boost.boosted_status, status) @@ -112,7 +121,7 @@ class InteractionViews(TestCase): self.assertFalse(models.Notification.objects.exists()) - def test_handle_boost_unlisted(self, _): + def test_boost_unlisted(self, _): """ boost a status """ view = views.Boost.as_view() request = self.factory.post("") @@ -127,7 +136,7 @@ class InteractionViews(TestCase): boost = models.Boost.objects.get() self.assertEqual(boost.privacy, "unlisted") - def test_handle_boost_private(self, _): + def test_boost_private(self, _): """ boost a status """ view = views.Boost.as_view() request = self.factory.post("") @@ -140,7 +149,7 @@ class InteractionViews(TestCase): view(request, status.id) self.assertFalse(models.Boost.objects.exists()) - def test_handle_boost_twice(self, _): + def test_boost_twice(self, _): """ boost a status """ view = views.Boost.as_view() request = self.factory.post("") @@ -152,7 +161,7 @@ class InteractionViews(TestCase): view(request, status.id) self.assertEqual(models.Boost.objects.count(), 1) - def test_handle_unboost(self, _): + def test_unboost(self, _): """ undo a boost """ view = views.Unboost.as_view() request = self.factory.post("") From a3f91d991f5e2f7ef91d4f6759b675740d5d1146 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 18:19:42 -0700 Subject: [PATCH 086/109] Remove tag form --- bookwyrm/forms.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 1f1f1a3b5..df68334e0 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -156,14 +156,6 @@ class UserGroupForm(CustomForm): fields = ["groups"] -class TagForm(CustomForm): - class Meta: - model = models.Tag - fields = ["name"] - help_texts = {f: None for f in fields} - labels = {"name": "Add a tag"} - - class CoverForm(CustomForm): class Meta: model = models.Book From 74ccaf27facd6b3f41fcad68bba28e9112b3f26a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 18:23:23 -0700 Subject: [PATCH 087/109] Tag removal migration --- .../migrations/0070_auto_20210423_0121.py | 35 +++++++++++++++++++ bookwyrm/templates/snippets/tag.html | 23 ------------ bookwyrm/templates/tag.html | 14 -------- bookwyrm/views/books.py | 7 ---- 4 files changed, 35 insertions(+), 44 deletions(-) create mode 100644 bookwyrm/migrations/0070_auto_20210423_0121.py delete mode 100644 bookwyrm/templates/snippets/tag.html delete mode 100644 bookwyrm/templates/tag.html diff --git a/bookwyrm/migrations/0070_auto_20210423_0121.py b/bookwyrm/migrations/0070_auto_20210423_0121.py new file mode 100644 index 000000000..90540ae12 --- /dev/null +++ b/bookwyrm/migrations/0070_auto_20210423_0121.py @@ -0,0 +1,35 @@ +# Generated by Django 3.1.8 on 2021-04-23 01:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0069_auto_20210422_1604'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='usertag', + unique_together=None, + ), + migrations.RemoveField( + model_name='usertag', + name='book', + ), + migrations.RemoveField( + model_name='usertag', + name='tag', + ), + migrations.RemoveField( + model_name='usertag', + name='user', + ), + migrations.DeleteModel( + name='Tag', + ), + migrations.DeleteModel( + name='UserTag', + ), + ] diff --git a/bookwyrm/templates/snippets/tag.html b/bookwyrm/templates/snippets/tag.html deleted file mode 100644 index 507def723..000000000 --- a/bookwyrm/templates/snippets/tag.html +++ /dev/null @@ -1,23 +0,0 @@ -{% load i18n %} -
    -
    - {% csrf_token %} - - - -
    - - {{ tag.tag.name }} - - {% if tag.tag.identifier in user_tags %} - - {% else %} - - {% endif %} -
    -
    -
    diff --git a/bookwyrm/templates/tag.html b/bookwyrm/templates/tag.html deleted file mode 100644 index b6fa67783..000000000 --- a/bookwyrm/templates/tag.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'layout.html' %} -{% load i18n %} -{% load bookwyrm_tags %} - -{% block title %}{{ tag.name }}{% endblock %} - -{% block content %} -
    -

    {% blocktrans %}Books tagged "{{ tag.name }}"{% endblocktrans %}

    - {% include 'snippets/book_tiles.html' with books=books.all %} -
    -{% endblock %} - - diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 0c61d1a20..34ebe0b68 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -57,12 +57,7 @@ class Book(View): ) reviews_page = paginated.get_page(request.GET.get("page")) - user_tags = readthroughs = user_shelves = other_edition_shelves = [] if request.user.is_authenticated: - user_tags = models.UserTag.objects.filter( - book=book, user=request.user - ).values_list("tag__identifier", flat=True) - readthroughs = models.ReadThrough.objects.filter( user=request.user, book=book, @@ -87,11 +82,9 @@ class Book(View): "review_count": reviews.count(), "ratings": reviews.filter(Q(content__isnull=True) | Q(content="")), "rating": reviews.aggregate(Avg("rating"))["rating__avg"], - "tags": models.UserTag.objects.filter(book=book), "lists": privacy_filter( request.user, book.list_set.filter(listitem__approved=True) ), - "user_tags": user_tags, "user_shelves": user_shelves, "other_edition_shelves": other_edition_shelves, "readthroughs": readthroughs, From f9c40aadd95e30ee852503d9cb975d7eeb7d86ff Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 18:30:58 -0700 Subject: [PATCH 088/109] Python formatting --- .../migrations/0070_auto_20210423_0121.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bookwyrm/migrations/0070_auto_20210423_0121.py b/bookwyrm/migrations/0070_auto_20210423_0121.py index 90540ae12..0b04c3ca2 100644 --- a/bookwyrm/migrations/0070_auto_20210423_0121.py +++ b/bookwyrm/migrations/0070_auto_20210423_0121.py @@ -6,30 +6,30 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0069_auto_20210422_1604'), + ("bookwyrm", "0069_auto_20210422_1604"), ] operations = [ migrations.AlterUniqueTogether( - name='usertag', + name="usertag", unique_together=None, ), migrations.RemoveField( - model_name='usertag', - name='book', + model_name="usertag", + name="book", ), migrations.RemoveField( - model_name='usertag', - name='tag', + model_name="usertag", + name="tag", ), migrations.RemoveField( - model_name='usertag', - name='user', + model_name="usertag", + name="user", ), migrations.DeleteModel( - name='Tag', + name="Tag", ), migrations.DeleteModel( - name='UserTag', + name="UserTag", ), ] From b457446f2ff69f850e927ae40e4bb025c3d9c260 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 22 Apr 2021 19:36:27 -0700 Subject: [PATCH 089/109] Don't save duplicate boosts --- bookwyrm/models/activitypub_mixin.py | 6 ++---- bookwyrm/models/status.py | 8 ++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 2e248fbe3..02cfafc0e 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -204,10 +204,8 @@ class ObjectMixin(ActivitypubMixin): created = created or not bool(self.id) # first off, we want to save normally no matter what super().save(*args, **kwargs) - if ( - not broadcast - or hasattr(self, "status_type") - and self.status_type == "Announce" + if not broadcast or ( + hasattr(self, "status_type") and self.status_type == "Announce" ): return diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 360288e93..65bf71d28 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -351,6 +351,14 @@ class Boost(ActivityMixin, Status): def save(self, *args, **kwargs): """ save and notify """ + # This constraint can't work as it would cross tables. + # class Meta: + # unique_together = ('user', 'boosted_status') + if Boost.objects.filter( + boosted_status=self.boosted_status, user=self.user + ).exists(): + return + super().save(*args, **kwargs) if not self.boosted_status.user.local or self.boosted_status.user == self.user: return From de19c7d7a6886a05e8d6761918e089ae5c8491d5 Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 23 Apr 2021 18:38:33 +0200 Subject: [PATCH 090/109] Update status_header.html --- bookwyrm/templates/snippets/status/status_header.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/status/status_header.html b/bookwyrm/templates/snippets/status/status_header.html index b833b92c0..7b2a6f77d 100644 --- a/bookwyrm/templates/snippets/status/status_header.html +++ b/bookwyrm/templates/snippets/status/status_header.html @@ -3,7 +3,7 @@ {% load humanize %}
    -
    +
    + {% endif %} + + {% for review in statuses %}
    - {% include 'snippets/pagination.html' with page=reviews path=book.local_path anchor="#reviews" %} + {% include 'snippets/pagination.html' with page=statuses path=book.local_path anchor="#reviews" %}
    diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 3ad064b23..b85a81e0c 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -260,7 +260,8 @@ urlpatterns = [ re_path(r"^boost/(?P\d+)/?$", views.Boost.as_view()), re_path(r"^unboost/(?P\d+)/?$", views.Unboost.as_view()), # books - re_path(r"%s(.json)?/?$" % book_path, views.Book.as_view()), + re_path(r"%s(.json)?/?$" % book_path, views.Book.as_view(), name="book"), + re_path(r"%s/(?Preview|comment|quote)/?$" % book_path, views.Book.as_view(), name="book-user-statuses"), re_path(r"%s/edit/?$" % book_path, views.EditBook.as_view()), re_path(r"%s/confirm/?$" % book_path, views.ConfirmEditBook.as_view()), re_path(r"^create-book/?$", views.EditBook.as_view()), diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 34ebe0b68..67b3792ef 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -28,7 +28,7 @@ from .helpers import is_api_request, get_edition, privacy_filter class Book(View): """ a book! this is the stuff """ - def get(self, request, book_id): + def get(self, request, book_id, user_statuses=False): """ info about a book """ try: book = models.Book.objects.select_subclasses().get(id=book_id) @@ -40,22 +40,42 @@ class Book(View): if isinstance(book, models.Work): book = book.get_default_edition() - if not book: + if not book or not book.parent_work: return HttpResponseNotFound() work = book.parent_work - if not work: - return HttpResponseNotFound() # all reviews for the book - reviews = models.Review.objects.filter(book__in=work.editions.all()) - reviews = privacy_filter(request.user, reviews) + reviews = privacy_filter( + request.user, + models.Review.objects.filter(book__in=work.editions.all()) + ) # the reviews to show - paginated = Paginator( - reviews.exclude(Q(content__isnull=True) | Q(content="")), PAGE_LENGTH - ) - reviews_page = paginated.get_page(request.GET.get("page")) + if user_statuses and request.user.is_authenticated: + if user_statuses == 'review': + queryset = book.review_set + elif user_statuses == 'comment': + queryset = book.comment_set + else: + queryset = book.quotation_set + paginated = Paginator( + queryset.filter(user=request.user), PAGE_LENGTH + ) + else: + paginated = Paginator( + reviews.exclude(Q(content__isnull=True) | Q(content="")), PAGE_LENGTH + ) + data = { + "book": book, + "statuses": paginated.get_page(request.GET.get("page")), + "review_count": reviews.count(), + "ratings": reviews.filter(Q(content__isnull=True) | Q(content="")), + "rating": reviews.aggregate(Avg("rating"))["rating__avg"], + "lists": privacy_filter( + request.user, book.list_set.filter(listitem__approved=True) + ), + } if request.user.is_authenticated: readthroughs = models.ReadThrough.objects.filter( @@ -67,29 +87,24 @@ class Book(View): readthrough.progress_updates = ( readthrough.progressupdate_set.all().order_by("-updated_date") ) + data["readthroughs"] = readthroughs - user_shelves = models.ShelfBook.objects.filter(user=request.user, book=book) + data["user_shelves"] = models.ShelfBook.objects.filter( + user=request.user, book=book + ) - other_edition_shelves = models.ShelfBook.objects.filter( + data["other_edition_shelves"] = models.ShelfBook.objects.filter( ~Q(book=book), user=request.user, book__parent_work=book.parent_work, ) - data = { - "book": book, - "reviews": reviews_page, - "review_count": reviews.count(), - "ratings": reviews.filter(Q(content__isnull=True) | Q(content="")), - "rating": reviews.aggregate(Avg("rating"))["rating__avg"], - "lists": privacy_filter( - request.user, book.list_set.filter(listitem__approved=True) - ), - "user_shelves": user_shelves, - "other_edition_shelves": other_edition_shelves, - "readthroughs": readthroughs, - "path": "/book/%s" % book_id, - } + data["user_statuses"] = { + "review_count": book.review_set.filter(user=request.user).count(), + "comment_count": book.comment_set.filter(user=request.user).count(), + "quotation_count": book.quotation_set.filter(user=request.user).count(), + } + return TemplateResponse(request, "book/book.html", data) From 888930f891c21b7ca6b11080e89dc9552ec8e9e1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 23 Apr 2021 13:35:12 -0700 Subject: [PATCH 096/109] User request path for pagination --- bookwyrm/templates/book/book.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index 31c245326..cfa400d62 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -316,7 +316,7 @@ {% endfor %}
    - {% include 'snippets/pagination.html' with page=statuses path=book.local_path anchor="#reviews" %} + {% include 'snippets/pagination.html' with page=statuses path=request.path anchor="#reviews" %}
    From 126594ec4935f1f6a863560f200371ae04c33d8e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 23 Apr 2021 13:46:22 -0700 Subject: [PATCH 097/109] Cleans up queryset declarations --- bookwyrm/templates/book/book.html | 2 +- bookwyrm/urls.py | 6 +++++- bookwyrm/views/books.py | 17 +++++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index cfa400d62..97f105bf7 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -251,7 +251,7 @@