diff --git a/.editorconfig b/.editorconfig index d102bc5ad..f2e8a1780 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,7 +32,7 @@ indent_size = 2 max_line_length = off # Computer generated files -[{package.json,*.lock,*.mo}] +[{icons.css,package.json,*.lock,*.mo}] indent_size = unset indent_style = unset max_line_length = unset diff --git a/.env.dev.example b/.env.dev.example index f42aaaaec..d4476fd24 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -43,6 +43,9 @@ EMAIL_HOST_PASSWORD=emailpassword123 EMAIL_USE_TLS=true EMAIL_USE_SSL=false +# Thumbnails Generation +ENABLE_THUMBNAIL_GENERATION=false + # S3 configuration USE_S3=false AWS_ACCESS_KEY_ID= @@ -58,6 +61,7 @@ AWS_SECRET_ACCESS_KEY= # AWS_S3_REGION_NAME=None # "fr-par" # AWS_S3_ENDPOINT_URL=None # "https://s3.fr-par.scw.cloud" + # Preview image generation can be computing and storage intensive # ENABLE_PREVIEW_IMAGES=True diff --git a/.env.prod.example b/.env.prod.example index 5115469ca..99520916a 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -43,6 +43,9 @@ EMAIL_HOST_PASSWORD=emailpassword123 EMAIL_USE_TLS=true EMAIL_USE_SSL=false +# Thumbnails Generation +ENABLE_THUMBNAIL_GENERATION=false + # S3 configuration USE_S3=false AWS_ACCESS_KEY_ID= @@ -58,6 +61,7 @@ AWS_SECRET_ACCESS_KEY= # AWS_S3_REGION_NAME=None # "fr-par" # AWS_S3_ENDPOINT_URL=None # "https://s3.fr-par.scw.cloud" + # Preview image generation can be computing and storage intensive # ENABLE_PREVIEW_IMAGES=True diff --git a/.github/workflows/curlylint.yaml b/.github/workflows/curlylint.yaml new file mode 100644 index 000000000..e27d0b1b3 --- /dev/null +++ b/.github/workflows/curlylint.yaml @@ -0,0 +1,28 @@ +name: Templates validator + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install curlylint + run: pip install curlylint + + - name: Run linter + run: > + curlylint --rule 'aria_role: true' \ + --rule 'django_forms_rendering: true' \ + --rule 'html_has_lang: true' \ + --rule 'image_alt: true' \ + --rule 'meta_viewport: true' \ + --rule 'no_autofocus: true' \ + --rule 'tabindex_no_positive: true' \ + --exclude '_modal.html|create_status/layout.html' \ + bookwyrm/templates diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index ddd45426f..52b1b1f27 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -106,8 +106,10 @@ class ActivityObject: value = field.default setattr(self, field.name, value) - # pylint: disable=too-many-locals,too-many-branches - def to_model(self, model=None, instance=None, allow_create=True, save=True): + # pylint: disable=too-many-locals,too-many-branches,too-many-arguments + def to_model( + self, model=None, instance=None, allow_create=True, save=True, overwrite=True + ): """convert from an activity to a model instance""" model = model or get_model_from_type(self.type) @@ -129,9 +131,12 @@ class ActivityObject: # keep track of what we've changed update_fields = [] + # sets field on the model using the activity value for field in instance.simple_fields: try: - changed = field.set_field_from_activity(instance, self) + changed = field.set_field_from_activity( + instance, self, overwrite=overwrite + ) if changed: update_fields.append(field.name) except AttributeError as e: @@ -140,7 +145,9 @@ class ActivityObject: # image fields have to be set after other fields because they can save # too early and jank up users for field in instance.image_fields: - changed = field.set_field_from_activity(instance, self, save=save) + changed = field.set_field_from_activity( + instance, self, save=save, overwrite=overwrite + ) if changed: update_fields.append(field.name) @@ -268,6 +275,8 @@ def resolve_remote_id( ): """take a remote_id and return an instance, creating if necessary""" if model: # a bonus check we can do if we already know the model + if isinstance(model, str): + model = apps.get_model(f"bookwyrm.{model}", require_ready=True) result = model.find_existing_by_remote_id(remote_id) if result and not refresh: return result if not get_activity else result.to_activity_dataclass() diff --git a/bookwyrm/activitypub/note.py b/bookwyrm/activitypub/note.py index 916da2d0e..aca62d7c5 100644 --- a/bookwyrm/activitypub/note.py +++ b/bookwyrm/activitypub/note.py @@ -30,8 +30,8 @@ class Note(ActivityObject): to: List[str] = field(default_factory=lambda: []) cc: List[str] = field(default_factory=lambda: []) replies: Dict = field(default_factory=lambda: {}) - inReplyTo: str = "" - summary: str = "" + inReplyTo: str = None + summary: str = None tag: List[Link] = field(default_factory=lambda: []) attachment: List[Document] = field(default_factory=lambda: []) sensitive: bool = False @@ -59,6 +59,9 @@ class Comment(Note): """like a note but with a book""" inReplyToBook: str + readingStatus: str = None + progress: int = None + progressMode: str = None type: str = "Comment" diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 621f06dab..a5f95ac9d 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -24,14 +24,15 @@ class ActivityStream(RedisStore): """statuses are sorted by date published""" return obj.published_date.timestamp() - def add_status(self, status): + def add_status(self, status, increment_unread=False): """add a status to users' feeds""" # the pipeline contains all the add-to-stream activities pipeline = self.add_object_to_related_stores(status, execute=False) - for user in self.get_audience(status): - # add to the unread status count - pipeline.incr(self.unread_id(user)) + if increment_unread: + for user in self.get_audience(status): + # add to the unread status count + pipeline.incr(self.unread_id(user)) # and go! pipeline.execute() @@ -262,12 +263,14 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): return # when creating new things, gotta wait on the transaction - transaction.on_commit(lambda: add_status_on_create_command(sender, instance)) + transaction.on_commit( + lambda: add_status_on_create_command(sender, instance, created) + ) -def add_status_on_create_command(sender, instance): +def add_status_on_create_command(sender, instance, created): """runs this code only after the database commit completes""" - add_status_task.delay(instance.id) + add_status_task.delay(instance.id, increment_unread_unread=created) if sender != models.Boost: return @@ -440,11 +443,11 @@ def remove_status_task(status_ids): @app.task -def add_status_task(status_id): +def add_status_task(status_id, increment_unread=False): """remove a status from any stream it might be in""" status = models.Status.objects.get(id=status_id) for stream in streams.values(): - stream.add_status(status) + stream.add_status(status, increment_unread=increment_unread) @app.task diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index fb102ea4b..ffacffdf0 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -139,7 +139,7 @@ class AbstractConnector(AbstractMinimalConnector): **dict_from_mappings(work_data, self.book_mappings) ) # this will dedupe automatically - work = work_activity.to_model(model=models.Work) + work = work_activity.to_model(model=models.Work, overwrite=False) for author in self.get_authors_from_data(work_data): work.authors.add(author) @@ -156,7 +156,7 @@ class AbstractConnector(AbstractMinimalConnector): mapped_data = dict_from_mappings(edition_data, self.book_mappings) mapped_data["work"] = work.remote_id edition_activity = activitypub.Edition(**mapped_data) - edition = edition_activity.to_model(model=models.Edition) + edition = edition_activity.to_model(model=models.Edition, overwrite=False) edition.connector = self.connector edition.save() @@ -182,7 +182,7 @@ class AbstractConnector(AbstractMinimalConnector): return None # this will dedupe - return activity.to_model(model=models.Author) + return activity.to_model(model=models.Author, overwrite=False) @abstractmethod def is_work_data(self, data): diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index 842d09974..d2a7b9faa 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -145,8 +145,8 @@ class Connector(AbstractConnector): def get_edition_from_work_data(self, data): data = self.load_edition_data(data.get("uri")) try: - uri = data["uris"][0] - except KeyError: + uri = data.get("uris", [])[0] + except IndexError: raise ConnectorException("Invalid book data") return self.get_book_data(self.get_remote_id(uri)) diff --git a/bookwyrm/context_processors.py b/bookwyrm/context_processors.py index 1f0387fe7..0610a8b9a 100644 --- a/bookwyrm/context_processors.py +++ b/bookwyrm/context_processors.py @@ -11,6 +11,7 @@ def site_settings(request): # pylint: disable=unused-argument return { "site": models.SiteSettings.objects.get(), "active_announcements": models.Announcement.active_announcements(), + "thumbnail_generation_enabled": settings.ENABLE_THUMBNAIL_GENERATION, "media_full_url": settings.MEDIA_FULL_URL, "preview_images_enabled": settings.ENABLE_PREVIEW_IMAGES, "request_protocol": request_protocol, diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index c9e795c3e..e88124702 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -86,6 +86,7 @@ class CommentForm(CustomForm): "privacy", "progress", "progress_mode", + "reading_status", ] diff --git a/bookwyrm/imagegenerators.py b/bookwyrm/imagegenerators.py new file mode 100644 index 000000000..1d065192e --- /dev/null +++ b/bookwyrm/imagegenerators.py @@ -0,0 +1,113 @@ +"""Generators for all the different thumbnail sizes""" +from imagekit import ImageSpec, register +from imagekit.processors import ResizeToFit + + +class BookXSmallWebp(ImageSpec): + """Handles XSmall size in Webp format""" + + processors = [ResizeToFit(80, 80)] + format = "WEBP" + options = {"quality": 95} + + +class BookXSmallJpg(ImageSpec): + """Handles XSmall size in Jpeg format""" + + processors = [ResizeToFit(80, 80)] + format = "JPEG" + options = {"quality": 95} + + +class BookSmallWebp(ImageSpec): + """Handles Small size in Webp format""" + + processors = [ResizeToFit(100, 100)] + format = "WEBP" + options = {"quality": 95} + + +class BookSmallJpg(ImageSpec): + """Handles Small size in Jpeg format""" + + processors = [ResizeToFit(100, 100)] + format = "JPEG" + options = {"quality": 95} + + +class BookMediumWebp(ImageSpec): + """Handles Medium size in Webp format""" + + processors = [ResizeToFit(150, 150)] + format = "WEBP" + options = {"quality": 95} + + +class BookMediumJpg(ImageSpec): + """Handles Medium size in Jpeg format""" + + processors = [ResizeToFit(150, 150)] + format = "JPEG" + options = {"quality": 95} + + +class BookLargeWebp(ImageSpec): + """Handles Large size in Webp format""" + + processors = [ResizeToFit(200, 200)] + format = "WEBP" + options = {"quality": 95} + + +class BookLargeJpg(ImageSpec): + """Handles Large size in Jpeg format""" + + processors = [ResizeToFit(200, 200)] + format = "JPEG" + options = {"quality": 95} + + +class BookXLargeWebp(ImageSpec): + """Handles XLarge size in Webp format""" + + processors = [ResizeToFit(250, 250)] + format = "WEBP" + options = {"quality": 95} + + +class BookXLargeJpg(ImageSpec): + """Handles XLarge size in Jpeg format""" + + processors = [ResizeToFit(250, 250)] + format = "JPEG" + options = {"quality": 95} + + +class BookXxLargeWebp(ImageSpec): + """Handles XxLarge size in Webp format""" + + processors = [ResizeToFit(500, 500)] + format = "WEBP" + options = {"quality": 95} + + +class BookXxLargeJpg(ImageSpec): + """Handles XxLarge size in Jpeg format""" + + processors = [ResizeToFit(500, 500)] + format = "JPEG" + options = {"quality": 95} + + +register.generator("bw:book:xsmall:webp", BookXSmallWebp) +register.generator("bw:book:xsmall:jpg", BookXSmallJpg) +register.generator("bw:book:small:webp", BookSmallWebp) +register.generator("bw:book:small:jpg", BookSmallJpg) +register.generator("bw:book:medium:webp", BookMediumWebp) +register.generator("bw:book:medium:jpg", BookMediumJpg) +register.generator("bw:book:large:webp", BookLargeWebp) +register.generator("bw:book:large:jpg", BookLargeJpg) +register.generator("bw:book:xlarge:webp", BookXLargeWebp) +register.generator("bw:book:xlarge:jpg", BookXLargeJpg) +register.generator("bw:book:xxlarge:webp", BookXxLargeWebp) +register.generator("bw:book:xxlarge:jpg", BookXxLargeJpg) diff --git a/bookwyrm/migrations/0083_auto_20210816_2022.py b/bookwyrm/migrations/0083_auto_20210816_2022.py new file mode 100644 index 000000000..ecf2778b7 --- /dev/null +++ b/bookwyrm/migrations/0083_auto_20210816_2022.py @@ -0,0 +1,56 @@ +# Generated by Django 3.2.4 on 2021-08-16 20:22 + +import bookwyrm.models.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0082_auto_20210806_2324"), + ] + + operations = [ + migrations.AddField( + model_name="comment", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "Toread"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + migrations.AddField( + model_name="quotation", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "Toread"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + migrations.AddField( + model_name="review", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "Toread"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/migrations/0084_auto_20210817_1916.py b/bookwyrm/migrations/0084_auto_20210817_1916.py new file mode 100644 index 000000000..6e826f99c --- /dev/null +++ b/bookwyrm/migrations/0084_auto_20210817_1916.py @@ -0,0 +1,56 @@ +# Generated by Django 3.2.4 on 2021-08-17 19:16 + +import bookwyrm.models.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0083_auto_20210816_2022"), + ] + + operations = [ + migrations.AlterField( + model_name="comment", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "To-Read"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + migrations.AlterField( + model_name="quotation", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "To-Read"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + migrations.AlterField( + model_name="review", + name="reading_status", + field=bookwyrm.models.fields.CharField( + blank=True, + choices=[ + ("to-read", "To-Read"), + ("reading", "Reading"), + ("read", "Read"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/migrations/0085_user_saved_lists.py b/bookwyrm/migrations/0085_user_saved_lists.py new file mode 100644 index 000000000..d4d9278c5 --- /dev/null +++ b/bookwyrm/migrations/0085_user_saved_lists.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.4 on 2021-08-23 18:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0084_auto_20210817_1916"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="saved_lists", + field=models.ManyToManyField( + related_name="saved_lists", to="bookwyrm.List" + ), + ), + ] diff --git a/bookwyrm/migrations/0086_auto_20210827_1727.py b/bookwyrm/migrations/0086_auto_20210827_1727.py new file mode 100644 index 000000000..ef6af206b --- /dev/null +++ b/bookwyrm/migrations/0086_auto_20210827_1727.py @@ -0,0 +1,40 @@ +# Generated by Django 3.2.4 on 2021-08-27 17:27 + +from django.db import migrations, models +import django.db.models.expressions + + +def normalize_readthrough_dates(app_registry, schema_editor): + """Find any invalid dates and reset them""" + db_alias = schema_editor.connection.alias + app_registry.get_model("bookwyrm", "ReadThrough").objects.using(db_alias).filter( + start_date__gt=models.F("finish_date") + ).update(start_date=models.F("finish_date")) + + +def reverse_func(apps, schema_editor): + """nothing to do here""" + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0085_user_saved_lists"), + ] + + operations = [ + migrations.RunPython(normalize_readthrough_dates, reverse_func), + migrations.AlterModelOptions( + name="readthrough", + options={"ordering": ("-start_date",)}, + ), + migrations.AddConstraint( + model_name="readthrough", + constraint=models.CheckConstraint( + check=models.Q( + ("finish_date__gte", django.db.models.expressions.F("start_date")) + ), + name="chronology", + ), + ), + ] diff --git a/bookwyrm/migrations/0086_auto_20210828_1724.py b/bookwyrm/migrations/0086_auto_20210828_1724.py new file mode 100644 index 000000000..212477118 --- /dev/null +++ b/bookwyrm/migrations/0086_auto_20210828_1724.py @@ -0,0 +1,49 @@ +# Generated by Django 3.2.4 on 2021-08-28 17:24 + +import bookwyrm.models.fields +from django.conf import settings +from django.db import migrations, models +from django.db.models import F, Value, CharField +from django.db.models.functions import Concat + + +def forwards_func(apps, schema_editor): + """generate followers url""" + db_alias = schema_editor.connection.alias + apps.get_model("bookwyrm", "User").objects.using(db_alias).annotate( + generated_url=Concat( + F("remote_id"), Value("/followers"), output_field=CharField() + ) + ).update(followers_url=models.F("generated_url")) + + +def reverse_func(apps, schema_editor): + """noop""" + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0085_user_saved_lists"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="followers_url", + field=bookwyrm.models.fields.CharField( + default="/followers", max_length=255 + ), + preserve_default=False, + ), + migrations.RunPython(forwards_func, reverse_func), + migrations.AlterField( + model_name="user", + name="followers", + field=models.ManyToManyField( + related_name="following", + through="bookwyrm.UserFollows", + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py b/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py new file mode 100644 index 000000000..cd5311619 --- /dev/null +++ b/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.4 on 2021-08-29 18:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0086_auto_20210827_1727"), + ("bookwyrm", "0086_auto_20210828_1724"), + ] + + operations = [] diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index a6aa5de2d..8bed69249 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -7,10 +7,16 @@ from django.db import models from django.dispatch import receiver from model_utils import FieldTracker from model_utils.managers import InheritanceManager +from imagekit.models import ImageSpecField from bookwyrm import activitypub from bookwyrm.preview_images import generate_edition_preview_image_task -from bookwyrm.settings import DOMAIN, DEFAULT_LANGUAGE, ENABLE_PREVIEW_IMAGES +from bookwyrm.settings import ( + DOMAIN, + DEFAULT_LANGUAGE, + ENABLE_PREVIEW_IMAGES, + ENABLE_THUMBNAIL_GENERATION, +) from .activitypub_mixin import OrderedCollectionPageMixin, ObjectMixin from .base_model import BookWyrmModel @@ -97,6 +103,40 @@ class Book(BookDataModel): objects = InheritanceManager() field_tracker = FieldTracker(fields=["authors", "title", "subtitle", "cover"]) + if ENABLE_THUMBNAIL_GENERATION: + cover_bw_book_xsmall_webp = ImageSpecField( + source="cover", id="bw:book:xsmall:webp" + ) + cover_bw_book_xsmall_jpg = ImageSpecField( + source="cover", id="bw:book:xsmall:jpg" + ) + cover_bw_book_small_webp = ImageSpecField( + source="cover", id="bw:book:small:webp" + ) + cover_bw_book_small_jpg = ImageSpecField(source="cover", id="bw:book:small:jpg") + cover_bw_book_medium_webp = ImageSpecField( + source="cover", id="bw:book:medium:webp" + ) + cover_bw_book_medium_jpg = ImageSpecField( + source="cover", id="bw:book:medium:jpg" + ) + cover_bw_book_large_webp = ImageSpecField( + source="cover", id="bw:book:large:webp" + ) + cover_bw_book_large_jpg = ImageSpecField(source="cover", id="bw:book:large:jpg") + cover_bw_book_xlarge_webp = ImageSpecField( + source="cover", id="bw:book:xlarge:webp" + ) + cover_bw_book_xlarge_jpg = ImageSpecField( + source="cover", id="bw:book:xlarge:jpg" + ) + cover_bw_book_xxlarge_webp = ImageSpecField( + source="cover", id="bw:book:xxlarge:webp" + ) + cover_bw_book_xxlarge_jpg = ImageSpecField( + source="cover", id="bw:book:xxlarge:jpg" + ) + @property def author_text(self): """format a list of authors""" diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index b58f81747..cc5a7bb55 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -66,7 +66,7 @@ class ActivitypubFieldMixin: self.activitypub_field = activitypub_field super().__init__(*args, **kwargs) - def set_field_from_activity(self, instance, data): + def set_field_from_activity(self, instance, data, overwrite=True): """helper function for assinging a value to the field. Returns if changed""" try: value = getattr(data, self.get_activitypub_field()) @@ -79,8 +79,15 @@ class ActivitypubFieldMixin: if formatted is None or formatted is MISSING or formatted == {}: return False + current_value = ( + getattr(instance, self.name) if hasattr(instance, self.name) else None + ) + # if we're not in overwrite mode, only continue updating the field if its unset + if current_value and not overwrite: + return False + # the field is unchanged - if hasattr(instance, self.name) and getattr(instance, self.name) == formatted: + if current_value == formatted: return False setattr(instance, self.name, formatted) @@ -210,12 +217,27 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField): ) # pylint: disable=invalid-name - def set_field_from_activity(self, instance, data): + def set_field_from_activity(self, instance, data, overwrite=True): + if not overwrite: + return False + original = getattr(instance, self.name) to = data.to cc = data.cc + + # we need to figure out who this is to get their followers link + for field in ["attributedTo", "owner", "actor"]: + if hasattr(data, field): + user_field = field + break + if not user_field: + raise ValidationError("No user field found for privacy", data) + user = activitypub.resolve_remote_id(getattr(data, user_field), model="User") + if to == [self.public]: setattr(instance, self.name, "public") + elif to == [user.followers_url]: + setattr(instance, self.name, "followers") elif cc == []: setattr(instance, self.name, "direct") elif self.public in cc: @@ -231,9 +253,7 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField): mentions = [u.remote_id for u in instance.mention_users.all()] # this is a link to the followers list # pylint: disable=protected-access - followers = instance.user.__class__._meta.get_field( - "followers" - ).field_to_activity(instance.user.followers) + followers = instance.user.followers_url if instance.privacy == "public": activity["to"] = [self.public] activity["cc"] = [followers] + mentions @@ -273,8 +293,11 @@ class ManyToManyField(ActivitypubFieldMixin, models.ManyToManyField): self.link_only = link_only super().__init__(*args, **kwargs) - def set_field_from_activity(self, instance, data): + def set_field_from_activity(self, instance, data, overwrite=True): """helper function for assinging a value to the field""" + if not overwrite and getattr(instance, self.name).exists(): + return False + value = getattr(data, self.get_activitypub_field()) formatted = self.field_from_activity(value) if formatted is None or formatted is MISSING: @@ -377,13 +400,16 @@ class ImageField(ActivitypubFieldMixin, models.ImageField): super().__init__(*args, **kwargs) # pylint: disable=arguments-differ - def set_field_from_activity(self, instance, data, save=True): + def set_field_from_activity(self, instance, data, save=True, overwrite=True): """helper function for assinging a value to the field""" value = getattr(data, self.get_activitypub_field()) formatted = self.field_from_activity(value) if formatted is None or formatted is MISSING: return False + if not overwrite and hasattr(instance, self.name): + return False + getattr(instance, self.name).save(*formatted, save=save) return True diff --git a/bookwyrm/models/readthrough.py b/bookwyrm/models/readthrough.py index df341c8b2..343d3c115 100644 --- a/bookwyrm/models/readthrough.py +++ b/bookwyrm/models/readthrough.py @@ -1,7 +1,8 @@ """ progress in a book """ -from django.db import models -from django.utils import timezone from django.core import validators +from django.db import models +from django.db.models import F, Q +from django.utils import timezone from .base_model import BookWyrmModel @@ -41,6 +42,16 @@ class ReadThrough(BookWyrmModel): ) return None + class Meta: + """Don't let readthroughs end before they start""" + + constraints = [ + models.CheckConstraint( + check=Q(finish_date__gte=F("start_date")), name="chronology" + ) + ] + ordering = ("-start_date",) + class ProgressUpdate(BookWyrmModel): """Store progress through a book in the database.""" diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 3c25f1af8..9274a5813 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -235,12 +235,31 @@ class GeneratedNote(Status): pure_type = "Note" -class Comment(Status): - """like a review but without a rating and transient""" +ReadingStatusChoices = models.TextChoices( + "ReadingStatusChoices", ["to-read", "reading", "read"] +) + + +class BookStatus(Status): + """Shared fields for comments, quotes, reviews""" book = fields.ForeignKey( "Edition", on_delete=models.PROTECT, activitypub_field="inReplyToBook" ) + pure_type = "Note" + + reading_status = fields.CharField( + max_length=255, choices=ReadingStatusChoices.choices, null=True, blank=True + ) + + class Meta: + """not a real model, sorry""" + + abstract = True + + +class Comment(BookStatus): + """like a review but without a rating and transient""" # this is it's own field instead of a foreign key to the progress update # so that the update can be deleted without impacting the status @@ -265,16 +284,12 @@ class Comment(Status): ) activity_serializer = activitypub.Comment - pure_type = "Note" -class Quotation(Status): +class Quotation(BookStatus): """like a review but without a rating and transient""" quote = fields.HtmlField() - book = fields.ForeignKey( - "Edition", on_delete=models.PROTECT, activitypub_field="inReplyToBook" - ) @property def pure_content(self): @@ -289,16 +304,12 @@ class Quotation(Status): ) activity_serializer = activitypub.Quotation - pure_type = "Note" -class Review(Status): +class Review(BookStatus): """a book review""" name = fields.CharField(max_length=255, null=True) - book = fields.ForeignKey( - "Edition", on_delete=models.PROTECT, activitypub_field="inReplyToBook" - ) rating = fields.DecimalField( default=None, null=True, diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index e10bcd293..0745dffa2 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -82,9 +82,9 @@ class User(OrderedCollectionPageMixin, AbstractUser): preview_image = models.ImageField( upload_to="previews/avatars/", blank=True, null=True ) - followers = fields.ManyToManyField( + followers_url = fields.CharField(max_length=255, activitypub_field="followers") + followers = models.ManyToManyField( "self", - link_only=True, symmetrical=False, through="UserFollows", through_fields=("user_object", "user_subject"), @@ -104,6 +104,9 @@ class User(OrderedCollectionPageMixin, AbstractUser): through_fields=("user_subject", "user_object"), related_name="blocked_by", ) + saved_lists = models.ManyToManyField( + "List", symmetrical=False, related_name="saved_lists" + ) favorites = models.ManyToManyField( "Status", symmetrical=False, @@ -225,7 +228,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): def to_followers_activity(self, **kwargs): """activitypub followers list""" - remote_id = "%s/followers" % self.remote_id + remote_id = self.followers_url return self.to_ordered_collection( self.followers.order_by("-updated_date").all(), remote_id=remote_id, @@ -272,10 +275,12 @@ class User(OrderedCollectionPageMixin, AbstractUser): return # populate fields for local users - self.remote_id = "%s/user/%s" % (site_link(), self.localname) - self.inbox = "%s/inbox" % self.remote_id - self.shared_inbox = "%s/inbox" % site_link() - self.outbox = "%s/outbox" % self.remote_id + link = site_link() + self.remote_id = f"{link}/user/{self.localname}" + self.followers_url = f"{self.remote_id}/followers" + self.inbox = f"{self.remote_id}/inbox" + self.shared_inbox = f"{link}/inbox" + self.outbox = f"{self.remote_id}/outbox" # an id needs to be set before we can proceed with related models super().save(*args, **kwargs) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index fa5c73a53..521e73b26 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -33,10 +33,11 @@ class RedisStore(ABC): # and go! return pipeline.execute() - def remove_object_from_related_stores(self, obj): + def remove_object_from_related_stores(self, obj, stores=None): """remove an object from all stores""" + stores = stores or self.get_stores_for_object(obj) pipeline = r.pipeline() - for store in self.get_stores_for_object(obj): + for store in stores: pipeline.zrem(store, -1, obj.id) pipeline.execute() diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 180191d98..c1f900794 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -75,6 +75,7 @@ INSTALLED_APPS = [ "django_rename_app", "bookwyrm", "celery", + "imagekit", "storages", ] @@ -191,6 +192,9 @@ USER_AGENT = "%s (BookWyrm/%s; +https://%s/)" % ( DOMAIN, ) +# Imagekit generated thumbnails +ENABLE_THUMBNAIL_GENERATION = env.bool("ENABLE_THUMBNAIL_GENERATION", False) +IMAGEKIT_CACHEFILE_DIR = "thumbnails" # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 8fbdcfc6c..0724c7f14 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -29,6 +29,10 @@ body { min-width: 75% !important; } +.modal-card-body { + max-height: 70vh; +} + .clip-text { max-height: 35em; overflow: hidden; @@ -232,16 +236,21 @@ body { /* Cover caption * -------------------------------------------------------------------------- */ -.no-cover .cover_caption { +.no-cover .cover-caption { position: absolute; top: 0; right: 0; bottom: 0; left: 0; - padding: 0.25em; + padding: 0.5em; font-size: 0.75em; color: white; background-color: #002549; + display: flex; + align-items: center; + justify-content: center; + white-space: initial; + text-align: center; } /** Avatars diff --git a/bookwyrm/static/css/fonts/icomoon.eot b/bookwyrm/static/css/fonts/icomoon.eot index 566fb13df..2c801b2b6 100644 Binary files a/bookwyrm/static/css/fonts/icomoon.eot and b/bookwyrm/static/css/fonts/icomoon.eot differ diff --git a/bookwyrm/static/css/fonts/icomoon.svg b/bookwyrm/static/css/fonts/icomoon.svg index 6be97327f..6327b19e6 100644 --- a/bookwyrm/static/css/fonts/icomoon.svg +++ b/bookwyrm/static/css/fonts/icomoon.svg @@ -33,13 +33,12 @@ - + - - - - + + + diff --git a/bookwyrm/static/css/fonts/icomoon.ttf b/bookwyrm/static/css/fonts/icomoon.ttf index 55df6418c..242ca7392 100644 Binary files a/bookwyrm/static/css/fonts/icomoon.ttf and b/bookwyrm/static/css/fonts/icomoon.ttf differ diff --git a/bookwyrm/static/css/fonts/icomoon.woff b/bookwyrm/static/css/fonts/icomoon.woff index fa53e8cf9..67b0f0a69 100644 Binary files a/bookwyrm/static/css/fonts/icomoon.woff and b/bookwyrm/static/css/fonts/icomoon.woff differ diff --git a/bookwyrm/static/css/vendor/icons.css b/bookwyrm/static/css/vendor/icons.css index c78af145d..db783c24f 100644 --- a/bookwyrm/static/css/vendor/icons.css +++ b/bookwyrm/static/css/vendor/icons.css @@ -1,156 +1,150 @@ - -/** @todo Replace icons with SVG symbols. - @see https://www.youtube.com/watch?v=9xXBYcWgCHA */ @font-face { - font-family: 'icomoon'; - src: url('../fonts/icomoon.eot?n5x55'); - src: url('../fonts/icomoon.eot?n5x55#iefix') format('embedded-opentype'), - url('../fonts/icomoon.ttf?n5x55') format('truetype'), - url('../fonts/icomoon.woff?n5x55') format('woff'), - url('../fonts/icomoon.svg?n5x55#icomoon') format('svg'); - font-weight: normal; - font-style: normal; - font-display: block; + font-family: 'icomoon'; + src: url('../fonts/icomoon.eot?19nagi'); + src: url('../fonts/icomoon.eot?19nagi#iefix') format('embedded-opentype'), + url('../fonts/icomoon.ttf?19nagi') format('truetype'), + url('../fonts/icomoon.woff?19nagi') format('woff'), + url('../fonts/icomoon.svg?19nagi#icomoon') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; } [class^="icon-"], [class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'icomoon' !important; - speak: never; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .icon-graphic-heart:before { - content: "\e91e"; + content: "\e91e"; } .icon-graphic-paperplane:before { - content: "\e91f"; + content: "\e91f"; } .icon-graphic-banknote:before { - content: "\e920"; -} -.icon-stars:before { - content: "\e91a"; + content: "\e920"; } .icon-warning:before { - content: "\e91b"; + content: "\e91b"; } .icon-book:before { - content: "\e900"; + content: "\e900"; } .icon-bookmark:before { - content: "\e91c"; + content: "\e91a"; } .icon-rss:before { - content: "\e91d"; + content: "\e91d"; } .icon-envelope:before { - content: "\e901"; + content: "\e901"; } .icon-arrow-right:before { - content: "\e902"; + content: "\e902"; } .icon-bell:before { - content: "\e903"; + content: "\e903"; } .icon-x:before { - content: "\e904"; + content: "\e904"; } .icon-quote-close:before { - content: "\e905"; + content: "\e905"; } .icon-quote-open:before { - content: "\e906"; + content: "\e906"; } .icon-image:before { - content: "\e907"; + content: "\e907"; } .icon-pencil:before { - content: "\e908"; + content: "\e908"; } .icon-list:before { - content: "\e909"; + content: "\e909"; } .icon-unlock:before { - content: "\e90a"; + content: "\e90a"; } .icon-unlisted:before { - content: "\e90a"; + content: "\e90a"; } .icon-globe:before { - content: "\e90b"; + content: "\e90b"; } .icon-public:before { - content: "\e90b"; + content: "\e90b"; } .icon-lock:before { - content: "\e90c"; + content: "\e90c"; } .icon-followers:before { - content: "\e90c"; + content: "\e90c"; } .icon-chain-broken:before { - content: "\e90d"; + content: "\e90d"; } .icon-chain:before { - content: "\e90e"; + content: "\e90e"; } .icon-comments:before { - content: "\e90f"; + content: "\e90f"; } .icon-comment:before { - content: "\e910"; + content: "\e910"; } .icon-boost:before { - content: "\e911"; + content: "\e911"; } .icon-arrow-left:before { - content: "\e912"; + content: "\e912"; } .icon-arrow-up:before { - content: "\e913"; + content: "\e913"; } .icon-arrow-down:before { - content: "\e914"; + content: "\e914"; } .icon-home:before { - content: "\e915"; + content: "\e915"; } .icon-local:before { - content: "\e916"; + content: "\e916"; } .icon-dots-three:before { - content: "\e917"; + content: "\e917"; } .icon-check:before { - content: "\e918"; + content: "\e918"; } .icon-dots-three-vertical:before { - content: "\e919"; + content: "\e919"; } .icon-search:before { - content: "\e986"; + content: "\e986"; } .icon-star-empty:before { - content: "\e9d7"; + content: "\e9d7"; } .icon-star-half:before { - content: "\e9d8"; + content: "\e9d8"; } .icon-star-full:before { - content: "\e9d9"; + content: "\e9d9"; } .icon-heart:before { - content: "\e9da"; + content: "\e9da"; } .icon-plus:before { - content: "\ea0a"; + content: "\ea0a"; } diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index a4002c2d3..894b1fb69 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -138,8 +138,11 @@ let BookWyrm = new class { * @return {undefined} */ toggleAction(event) { - event.preventDefault(); let trigger = event.currentTarget; + + if (!trigger.dataset.allowDefault || event.currentTarget == event.target) { + event.preventDefault(); + } let pressed = trigger.getAttribute('aria-pressed') === 'false'; let targetId = trigger.dataset.controls; @@ -177,6 +180,13 @@ let BookWyrm = new class { this.toggleCheckbox(checkbox, pressed); } + // Toggle form disabled, if appropriate + let disable = trigger.dataset.disables; + + if (disable) { + this.toggleDisabled(disable, !pressed); + } + // Set focus, if appropriate. let focus = trigger.dataset.focusTarget; @@ -227,6 +237,17 @@ let BookWyrm = new class { document.getElementById(checkbox).checked = !!pressed; } + /** + * Enable or disable a form element or fieldset + * + * @param {string} form_element - id of the element + * @param {boolean} pressed - Is the trigger pressed? + * @return {undefined} + */ + toggleDisabled(form_element, pressed) { + document.getElementById(form_element).disabled = !!pressed; + } + /** * Give the focus to an element. * Only move the focus based on user interactions. diff --git a/bookwyrm/storage_backends.py b/bookwyrm/storage_backends.py index e10dfb841..4fb0feff0 100644 --- a/bookwyrm/storage_backends.py +++ b/bookwyrm/storage_backends.py @@ -1,4 +1,6 @@ """Handles backends for storages""" +import os +from tempfile import SpooledTemporaryFile from storages.backends.s3boto3 import S3Boto3Storage @@ -15,3 +17,33 @@ class ImagesStorage(S3Boto3Storage): # pylint: disable=abstract-method location = "images" default_acl = "public-read" file_overwrite = False + + """ + This is our custom version of S3Boto3Storage that fixes a bug in + boto3 where the passed in file is closed upon upload. + From: + https://github.com/matthewwithanm/django-imagekit/issues/391#issuecomment-275367006 + https://github.com/boto/boto3/issues/929 + https://github.com/matthewwithanm/django-imagekit/issues/391 + """ + + def _save(self, name, content): + """ + We create a clone of the content file as when this is passed to + boto3 it wrongly closes the file upon upload where as the storage + backend expects it to still be open + """ + # Seek our content back to the start + content.seek(0, os.SEEK_SET) + + # Create a temporary file that will write to disk after a specified + # size. This file will be automatically deleted when closed by + # boto3 or after exiting the `with` statement if the boto3 is fixed + with SpooledTemporaryFile() as content_autoclose: + + # Write our original content into our copy that will be closed by boto3 + content_autoclose.write(content.read()) + + # Upload the object which will auto close the + # content_autoclose instance + return super()._save(name, content_autoclose) diff --git a/bookwyrm/templates/author/author.html b/bookwyrm/templates/author/author.html index 1c409d062..77c7b901d 100644 --- a/bookwyrm/templates/author/author.html +++ b/bookwyrm/templates/author/author.html @@ -57,7 +57,7 @@ {% if author.wikipedia_link %}

- + {% trans "Wikipedia" %}

diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index 2e8ff0d04..e504041bb 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -62,7 +62,7 @@
- {% include 'snippets/book_cover.html' with book=book cover_class='is-h-m-mobile' %} + {% include 'snippets/book_cover.html' with size='xxlarge' size_mobile='medium' book=book cover_class='is-h-m-mobile' %} {% include 'snippets/rate_action.html' with user=request.user book=book %}
@@ -134,7 +134,7 @@
{% csrf_token %}

- +

diff --git a/bookwyrm/templates/book/edit_book.html b/bookwyrm/templates/book/edit_book.html index 32018a251..2f6ca3242 100644 --- a/bookwyrm/templates/book/edit_book.html +++ b/bookwyrm/templates/book/edit_book.html @@ -42,11 +42,18 @@
{% endif %} -{% if book %} - -{% else %} - -{% endif %} + {% csrf_token %} {% if confirm_mode %} @@ -220,7 +227,7 @@

{% trans "Cover" %}

- {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xl-mobile is-w-auto-tablet' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xl-mobile is-w-auto-tablet' size_mobile='xlarge' size='large' %}
diff --git a/bookwyrm/templates/book/edition_filters.html b/bookwyrm/templates/book/edition_filters.html index a55b72af0..c41ab0c01 100644 --- a/bookwyrm/templates/book/edition_filters.html +++ b/bookwyrm/templates/book/edition_filters.html @@ -1,6 +1,7 @@ {% extends 'snippets/filters_panel/filters_panel.html' %} {% block filter_fields %} +{% include 'book/search_filter.html' %} {% include 'book/language_filter.html' %} {% include 'book/format_filter.html' %} {% endblock %} diff --git a/bookwyrm/templates/book/editions.html b/bookwyrm/templates/book/editions.html index e2a0bdda5..7a4338f12 100644 --- a/bookwyrm/templates/book/editions.html +++ b/bookwyrm/templates/book/editions.html @@ -15,7 +15,7 @@
diff --git a/bookwyrm/templates/book/readthrough.html b/bookwyrm/templates/book/readthrough.html index 05ed3c639..12430f75b 100644 --- a/bookwyrm/templates/book/readthrough.html +++ b/bookwyrm/templates/book/readthrough.html @@ -6,7 +6,6 @@
{% trans "Progress Updates:" %} -
    {% if readthrough.finish_date or readthrough.progress %}
  • diff --git a/bookwyrm/templates/book/search_filter.html b/bookwyrm/templates/book/search_filter.html new file mode 100644 index 000000000..f2345a688 --- /dev/null +++ b/bookwyrm/templates/book/search_filter.html @@ -0,0 +1,8 @@ +{% extends 'snippets/filters_panel/filter_field.html' %} +{% load i18n %} + +{% block filter %} + + +{% endblock %} + diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index 81654d576..6d80c3daf 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -10,7 +10,7 @@ {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} + >{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' size='xxlarge' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %}

    diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html index 79fbd77c8..5b2070188 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/discover/small-book.html @@ -6,7 +6,7 @@ {% if status.book or status.mention_books.exists %} {% load_book status as book %} - {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto align to-b to-l' %} + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto align to-b to-l' size='xxlarge' %}
    diff --git a/bookwyrm/templates/email/preview.html b/bookwyrm/templates/email/preview.html index 66d856c08..ab4323054 100644 --- a/bookwyrm/templates/email/preview.html +++ b/bookwyrm/templates/email/preview.html @@ -1,4 +1,4 @@ - +
    Subject: {% include subject_path %} diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 39eebb26d..265a467a7 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -40,11 +40,10 @@ {% if suggested_users %} {# suggested users for when things are very lonely #} {% include 'feed/suggested_users.html' with suggested_users=suggested_users %} + {% endif %}
    {% endif %} -{% endif %} - {% for activity in activities %} {% if not activities.number > 1 and forloop.counter0 == 2 and suggested_users %} diff --git a/bookwyrm/templates/feed/suggested_users.html b/bookwyrm/templates/feed/suggested_users.html index c095faa55..1de1ae139 100644 --- a/bookwyrm/templates/feed/suggested_users.html +++ b/bookwyrm/templates/feed/suggested_users.html @@ -2,5 +2,5 @@

    {% trans "Who to follow" %}

    {% include 'snippets/suggested_users.html' with suggested_users=suggested_users %} - View directory + {% trans "View directory" %}
    diff --git a/bookwyrm/templates/get_started/book_preview.html b/bookwyrm/templates/get_started/book_preview.html index d8941ad50..893e7593a 100644 --- a/bookwyrm/templates/get_started/book_preview.html +++ b/bookwyrm/templates/get_started/book_preview.html @@ -1,6 +1,6 @@ {% load i18n %}
    - {% include 'snippets/book_cover.html' with book=book cover_class='is-h-l is-h-m-mobile' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-h-l is-h-m-mobile' size_mobile='medium' size='large' %}
    +{% endblock %} + +{% block reading-dates %} +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +{% endblock %} diff --git a/bookwyrm/templates/snippets/reading_modals/form.html b/bookwyrm/templates/snippets/reading_modals/form.html new file mode 100644 index 000000000..d1ba916ff --- /dev/null +++ b/bookwyrm/templates/snippets/reading_modals/form.html @@ -0,0 +1,15 @@ +{% extends "snippets/create_status/layout.html" %} +{% load i18n %} + +{% block form_open %}{% endblock %} + +{% block content_label %} +{% trans "Comment:" %} +{% trans "(Optional)" %} +{% endblock %} + +{% block initial_fields %} + + + +{% endblock %} diff --git a/bookwyrm/templates/snippets/reading_modals/layout.html b/bookwyrm/templates/snippets/reading_modals/layout.html new file mode 100644 index 000000000..0f5dedb0a --- /dev/null +++ b/bookwyrm/templates/snippets/reading_modals/layout.html @@ -0,0 +1,28 @@ +{% extends 'components/modal.html' %} +{% load i18n %} +{% load utilities %} + +{% block modal-body %} + +{% block reading-dates %}{% endblock %} + +{% with 0|uuid as local_uuid %} +
    + + +
    + +
    + +
    + {% include "snippets/reading_modals/form.html" with optional=True %} +
    +
    +{% endwith %} + +{% endblock %} diff --git a/bookwyrm/templates/snippets/shelve_button/progress_update_modal.html b/bookwyrm/templates/snippets/reading_modals/progress_update_modal.html similarity index 100% rename from bookwyrm/templates/snippets/shelve_button/progress_update_modal.html rename to bookwyrm/templates/snippets/reading_modals/progress_update_modal.html diff --git a/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html b/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html new file mode 100644 index 000000000..099fd9153 --- /dev/null +++ b/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html @@ -0,0 +1,24 @@ +{% extends 'snippets/reading_modals/layout.html' %} +{% load i18n %} +{% load utilities %} + +{% block modal-title %} +{% blocktrans trimmed with book_title=book|book_title %} +Start "{{ book_title }}" +{% endblocktrans %} +{% endblock %} + +{% block modal-form-open %} + + +{% csrf_token %} +{% endblock %} + +{% block reading-dates %} +
    + + +
    +{% endblock %} diff --git a/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html b/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html new file mode 100644 index 000000000..1213b18e9 --- /dev/null +++ b/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html @@ -0,0 +1,15 @@ +{% extends 'snippets/reading_modals/layout.html' %} +{% load i18n %} +{% load utilities %} + +{% block modal-title %} +{% blocktrans trimmed with book_title=book|book_title %} +Want to Read "{{ book_title }}" +{% endblocktrans %} +{% endblock %} + +{% block modal-form-open %} + + +{% csrf_token %} +{% endblock %} diff --git a/bookwyrm/templates/snippets/search_result_text.html b/bookwyrm/templates/snippets/search_result_text.html index e39d34104..40fa5a3d5 100644 --- a/bookwyrm/templates/snippets/search_result_text.html +++ b/bookwyrm/templates/snippets/search_result_text.html @@ -1,7 +1,7 @@ {% load i18n %}
    - {% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' img_path=false %} + {% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' external_path=True %}
    @@ -10,7 +10,7 @@ {{ result.title }} diff --git a/bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html b/bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html deleted file mode 100644 index 36addc7b8..000000000 --- a/bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html +++ /dev/null @@ -1,48 +0,0 @@ -{% extends 'components/modal.html' %} -{% load i18n %} - -{% block modal-title %} -{% blocktrans with book_title=book.title %}Finish "{{ book_title }}"{% endblocktrans %} -{% endblock %} - - -{% block modal-form-open %} - -{% endblock %} - -{% block modal-body %} - -{% endblock %} - -{% block modal-footer %} -
    -
    - - {% include 'snippets/privacy_select.html' %} -
    -
    - - {% trans "Cancel" as button_text %} - {% include 'snippets/toggle/close_button.html' with text=button_text controls_text="finish-reading" controls_uid=uuid %} -
    -
    -{% endblock %} -{% block modal-form-close %}{% endblock %} diff --git a/bookwyrm/templates/snippets/shelve_button/shelve_button.html b/bookwyrm/templates/snippets/shelve_button/shelve_button.html index 40a9f6e73..189418122 100644 --- a/bookwyrm/templates/snippets/shelve_button/shelve_button.html +++ b/bookwyrm/templates/snippets/shelve_button/shelve_button.html @@ -19,13 +19,13 @@ {% endif %}
    -{% include 'snippets/shelve_button/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid %} +{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid %} -{% include 'snippets/shelve_button/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid %} +{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid %} -{% include 'snippets/shelve_button/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid readthrough=readthrough %} +{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid readthrough=readthrough %} -{% include 'snippets/shelve_button/progress_update_modal.html' with book=active_shelf_book.book controls_text="progress_update" controls_uid=uuid readthrough=readthrough %} +{% include 'snippets/reading_modals/progress_update_modal.html' with book=active_shelf_book.book controls_text="progress_update" controls_uid=uuid readthrough=readthrough %} {% endwith %} {% endif %} diff --git a/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html b/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html index 41e0c9ba7..5cce1477c 100644 --- a/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html +++ b/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html @@ -13,7 +13,9 @@ {% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %} {% endif %}{% elif shelf.identifier == 'read' and active_shelf.shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %} - {% endif %}{% elif shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %} {% trans "Finish reading" as button_text %} diff --git a/bookwyrm/templates/snippets/shelve_button/start_reading_modal.html b/bookwyrm/templates/snippets/shelve_button/start_reading_modal.html deleted file mode 100644 index 1858313b3..000000000 --- a/bookwyrm/templates/snippets/shelve_button/start_reading_modal.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends 'components/modal.html' %} -{% load i18n %} - -{% block modal-title %} -{% blocktrans trimmed with book_title=book.title %} -Start "{{ book_title }}" -{% endblocktrans %} -{% endblock %} - -{% block modal-form-open %} -
    -{% endblock %} - -{% block modal-body %} - -{% endblock %} - -{% block modal-footer %} -
    -
    - - {% include 'snippets/privacy_select.html' %} -
    -
    - - {% trans "Cancel" as button_text %} - {% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="start-reading" controls_uid=uuid %} -
    -
    -{% endblock %} -{% block modal-form-close %}
    {% endblock %} diff --git a/bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html b/bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html deleted file mode 100644 index 643e4a202..000000000 --- a/bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends 'components/modal.html' %} -{% load i18n %} - -{% block modal-title %} -{% blocktrans with book_title=book.title %}Want to Read "{{ book_title }}"{% endblocktrans %} -{% endblock %} - -{% block modal-form-open %} -
    - {% csrf_token %} - - -{% endblock %} - -{% block modal-footer %} -
    -
    - - {% include 'snippets/privacy_select.html' %} -
    -
    - - {% trans "Cancel" as button_text %} - {% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="want-to-read" controls_uid=uuid %} -
    -
    -{% endblock %} -{% block modal-form-close %}
    {% endblock %} diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html index ec959d592..781af2793 100644 --- a/bookwyrm/templates/snippets/status/content_status.html +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -19,7 +19,7 @@
    - {% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-mobile is-h-l-tablet' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-mobile is-h-l-tablet' size_mobile='medium' size='large' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html index 71ce2d99a..e73b9c320 100644 --- a/bookwyrm/templates/snippets/status/generated_status.html +++ b/bookwyrm/templates/snippets/status/generated_status.html @@ -8,7 +8,7 @@ {% with book=status.book|default:status.mention_books.first %}
    - {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xs is-h-s-tablet' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-h-xs is-h-s-tablet' size='small' size_mobile='xsmall' %}
    diff --git a/bookwyrm/templates/snippets/status/headers/comment.html b/bookwyrm/templates/snippets/status/headers/comment.html index 6886cfed6..88ba30ca6 100644 --- a/bookwyrm/templates/snippets/status/headers/comment.html +++ b/bookwyrm/templates/snippets/status/headers/comment.html @@ -1,2 +1,2 @@ {% load i18n %}{% load utilities %} -{% blocktrans with book_path=book.local_path book=status.book|book_title %}commented on {{ book }}{% endblocktrans %} +{% blocktrans with book_path=status.book.local_path book=status.book|book_title %}commented on {{ book }}{% endblocktrans %} diff --git a/bookwyrm/templates/snippets/status/headers/read.html b/bookwyrm/templates/snippets/status/headers/read.html index f942c0f0a..bc6147dfe 100644 --- a/bookwyrm/templates/snippets/status/headers/read.html +++ b/bookwyrm/templates/snippets/status/headers/read.html @@ -1,7 +1,8 @@ {% spaceless %} -{% load i18n %}{% load utilities %} +{% load i18n %} +{% load utilities %} +{% load status_display %} -{% with book=status.mention_books.first %} +{% load_book status as book %} {% blocktrans with book_path=book.remote_id book=book|book_title %}finished reading {{ book }}{% endblocktrans %} -{% endwith %} {% endspaceless %} diff --git a/bookwyrm/templates/snippets/status/headers/reading.html b/bookwyrm/templates/snippets/status/headers/reading.html index 460c4cae7..e8b51f7ba 100644 --- a/bookwyrm/templates/snippets/status/headers/reading.html +++ b/bookwyrm/templates/snippets/status/headers/reading.html @@ -1,9 +1,8 @@ {% spaceless %} {% load i18n %} {% load utilities %} +{% load status_display %} -{% with book=status.mention_books.first %} +{% load_book status as book %} {% blocktrans with book_path=book.remote_id book=book|book_title %}started reading {{ book }}{% endblocktrans %} -{% endwith %} - {% endspaceless %} diff --git a/bookwyrm/templates/snippets/status/headers/to_read.html b/bookwyrm/templates/snippets/status/headers/to_read.html index 7b89a775b..c252e71d6 100644 --- a/bookwyrm/templates/snippets/status/headers/to_read.html +++ b/bookwyrm/templates/snippets/status/headers/to_read.html @@ -1,8 +1,8 @@ {% spaceless %} {% load i18n %} {% load utilities %} +{% load status_display %} -{% with book=status.mention_books.first %} +{% load_book status as book %} {% blocktrans with book_path=book.remote_id book=book|book_title %}{{ username }} wants to read {{ book }}{% endblocktrans %} -{% endwith %} {% endspaceless %} diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index d2e8bc308..e0227a449 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -25,7 +25,7 @@
    {{ full }}
    @@ -41,7 +41,7 @@
    {{ full }}
    diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html old mode 100644 new mode 100755 index 41d52812f..8ca3bd180 --- a/bookwyrm/templates/user/layout.html +++ b/bookwyrm/templates/user/layout.html @@ -31,8 +31,8 @@ {% spaceless %}
    {{ user.summary|to_markdown|safe }} - {% endspaceless %}
    + {% endspaceless %} {% endif %}
    {% if not is_self and request.user.is_authenticated %} diff --git a/bookwyrm/templates/user/lists.html b/bookwyrm/templates/user/lists.html old mode 100644 new mode 100755 diff --git a/bookwyrm/templates/user/shelf/shelf.html b/bookwyrm/templates/user/shelf/shelf.html index 32cad25d3..61458fcc9 100644 --- a/bookwyrm/templates/user/shelf/shelf.html +++ b/bookwyrm/templates/user/shelf/shelf.html @@ -1,4 +1,4 @@ -{% extends 'user/layout.html' %} +{% extends 'layout.html' %} {% load bookwyrm_tags %} {% load utilities %} {% load humanize %} @@ -8,15 +8,17 @@ {% include 'user/shelf/books_header.html' %} {% endblock %} -{% block header %} -
    +{% block opengraph_images %} + {% include 'snippets/opengraph_images.html' with image=user.preview_image %} +{% endblock %} + +{% block content %} +

    {% include 'user/shelf/books_header.html' %}

    -{% endblock %} -{% block tabs %}
    @@ -41,9 +43,7 @@
    {% endif %}
    -{% endblock %} -{% block panel %}
    {% include 'user/shelf/create_shelf_form.html' with controls_text='create_shelf_form' %}
    @@ -94,7 +94,7 @@ {% spaceless %} - {% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-tablet is-h-s' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-w-s-tablet is-h-s' size='small' %} {{ book.title }} diff --git a/bookwyrm/templates/user/user.html b/bookwyrm/templates/user/user.html old mode 100644 new mode 100755 index ee9249776..f360a30af --- a/bookwyrm/templates/user/user.html +++ b/bookwyrm/templates/user/user.html @@ -35,7 +35,7 @@ {% for book in shelf.books %} {% endfor %} @@ -71,7 +71,7 @@ {% endfor %} {% if not activities %}
    -

    {% trans "No activities yet!" %} +

    {% trans "No activities yet!" %}

    {% endif %} diff --git a/bookwyrm/templates/user/user_preview.html b/bookwyrm/templates/user/user_preview.html old mode 100644 new mode 100755 diff --git a/bookwyrm/templates/widgets/clearable_file_input_with_warning.html b/bookwyrm/templates/widgets/clearable_file_input_with_warning.html index e4906cb9a..6370ba390 100644 --- a/bookwyrm/templates/widgets/clearable_file_input_with_warning.html +++ b/bookwyrm/templates/widgets/clearable_file_input_with_warning.html @@ -2,23 +2,30 @@ {% load utilities %} {% if widget.is_initial %} -

    - {{ widget.initial_text }}: - {{ widget.value|truncatepath:10 }} -

    -{% if not widget.required %} -

    -

    + {{ widget.initial_text }}: + {{ widget.value|truncatepath:10 }} +

    + + {% if not widget.required %} +

    + {% endif %} -

    -

    -{{ widget.input_text }}: -{% else %} -

    + +

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

    + {% if widget.is_initial %} + {{ widget.input_text }}: + {% endif %} + + +

    diff --git a/bookwyrm/templatetags/interaction.py b/bookwyrm/templatetags/interaction.py index bbe74600c..64c91f895 100644 --- a/bookwyrm/templatetags/interaction.py +++ b/bookwyrm/templatetags/interaction.py @@ -16,3 +16,9 @@ def get_user_liked(user, status): def get_user_boosted(user, status): """did the given user fav a status?""" return status.boosters.filter(user=user).exists() + + +@register.filter(name="saved") +def get_user_saved_lists(user, book_list): + """did the user save a list""" + return user.saved_lists.filter(id=book_list.id).exists() diff --git a/bookwyrm/templatetags/status_display.py b/bookwyrm/templatetags/status_display.py index 0d0137757..c92b1877a 100644 --- a/bookwyrm/templatetags/status_display.py +++ b/bookwyrm/templatetags/status_display.py @@ -70,7 +70,13 @@ def get_header_template(status): """get the path for the status template""" if isinstance(status, models.Boost): status = status.boosted_status - filename = "snippets/status/headers/{:s}.html".format(status.status_type.lower()) + try: + header_type = status.reading_status.replace("-", "_") + if not header_type: + raise AttributeError() + except AttributeError: + header_type = status.status_type.lower() + filename = f"snippets/status/headers/{header_type}.html" header_template = select_template([filename, "snippets/status/headers/note.html"]) return header_template.render({"status": status}) diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py index 23b6685d6..abb524998 100644 --- a/bookwyrm/templatetags/utilities.py +++ b/bookwyrm/templatetags/utilities.py @@ -3,6 +3,7 @@ import os from uuid import uuid4 from django import template from django.utils.translation import gettext_lazy as _ +from django.templatetags.static import static register = template.Library() @@ -50,3 +51,15 @@ def truncatepath(value, arg): except ValueError: # invalid literal for int() return path_list[-1] # Fail silently. return "%s/…%s" % (path_list[0], path_list[-1][-length:]) + + +@register.simple_tag(takes_context=False) +def get_book_cover_thumbnail(book, size="medium", ext="jpg"): + """Returns a book thumbnail at the specified size and extension, with fallback if needed""" + if size == "": + size = "medium" + try: + cover_thumbnail = getattr(book, "cover_bw_book_%s_%s" % (size, ext)) + return cover_thumbnail.url + except OSError: + return static("images/no_cover.jpg") diff --git a/bookwyrm/tests/activitypub/test_person.py b/bookwyrm/tests/activitypub/test_person.py index 67aaf891e..2722aaefd 100644 --- a/bookwyrm/tests/activitypub/test_person.py +++ b/bookwyrm/tests/activitypub/test_person.py @@ -25,3 +25,4 @@ class Person(TestCase): self.assertEqual(user.username, "mouse@example.com") self.assertEqual(user.remote_id, "https://example.com/user/mouse") self.assertFalse(user.local) + self.assertEqual(user.followers_url, "https://example.com/user/mouse/followers") diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 2520a2fd2..6730d37b9 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -146,6 +146,15 @@ class ModelFields(TestCase): def test_privacy_field_set_field_from_activity(self, _): """translate between to/cc fields and privacy""" + with patch("bookwyrm.models.user.set_remote_server.delay"): + test_user = User.objects.create_user( + username="test_user@example.com", + local=False, + remote_id="https://example.com/test_user", + inbox="https://example.com/users/test_user/inbox", + followers_url="https://example.com/users/test_user/followers", + ) + @dataclass(init=False) class TestActivity(ActivityObject): """real simple mock""" @@ -154,6 +163,7 @@ class ModelFields(TestCase): cc: List[str] id: str = "http://hi.com" type: str = "Test" + attributedTo: str = test_user.remote_id class TestPrivacyModel(ActivitypubMixin, BookWyrmModel): """real simple mock model because BookWyrmModel is abstract""" @@ -185,6 +195,16 @@ class ModelFields(TestCase): instance.set_field_from_activity(model_instance, data) self.assertEqual(model_instance.privacy_field, "unlisted") + data.to = [test_user.followers_url] + data.cc = [] + instance.set_field_from_activity(model_instance, data) + self.assertEqual(model_instance.privacy_field, "followers") + + data.to = ["http://user_remote/followers"] + data.cc = ["http://mentioned_user/remote_id"] + instance.set_field_from_activity(model_instance, data) + self.assertEqual(model_instance.privacy_field, "followers") + @patch("bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast") @patch("bookwyrm.activitystreams.ActivityStream.add_status") def test_privacy_field_set_activity_from_field(self, *_): diff --git a/bookwyrm/tests/models/test_readthrough_model.py b/bookwyrm/tests/models/test_readthrough_model.py index 596753f79..2b6e4fdd2 100644 --- a/bookwyrm/tests/models/test_readthrough_model.py +++ b/bookwyrm/tests/models/test_readthrough_model.py @@ -1,7 +1,9 @@ """ testing models """ +import datetime from unittest.mock import patch from django.test import TestCase from django.core.exceptions import ValidationError +from django.utils import timezone from bookwyrm import models @@ -21,27 +23,79 @@ class ReadThrough(TestCase): title="Example Edition", parent_work=self.work ) - self.readthrough = models.ReadThrough.objects.create( - user=self.user, book=self.edition + def test_valid_date(self): + """can't finish a book before you start it""" + start = timezone.now() + finish = start + datetime.timedelta(days=1) + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + finish_date=finish, + ) + + def test_valid_date_null_start(self): + """can't finish a book before you start it""" + start = timezone.now() + finish = start + datetime.timedelta(days=1) + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + finish_date=finish, + ) + + def test_valid_date_null_finish(self): + """can't finish a book before you start it""" + start = timezone.now() + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + ) + + def test_valid_date_null(self): + """can't finish a book before you start it""" + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + ) + + def test_valid_date_same(self): + """can't finish a book before you start it""" + start = timezone.now() + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + finish_date=start, ) def test_progress_update(self): """Test progress updates""" - self.readthrough.create_update() # No-op, no progress yet - self.readthrough.progress = 10 - self.readthrough.create_update() - self.readthrough.progress = 20 - self.readthrough.progress_mode = models.ProgressMode.PERCENT - self.readthrough.create_update() + readthrough = models.ReadThrough.objects.create( + user=self.user, book=self.edition + ) - updates = self.readthrough.progressupdate_set.order_by("created_date").all() + readthrough.create_update() # No-op, no progress yet + readthrough.progress = 10 + readthrough.create_update() + readthrough.progress = 20 + readthrough.progress_mode = models.ProgressMode.PERCENT + readthrough.create_update() + + updates = readthrough.progressupdate_set.order_by("created_date").all() self.assertEqual(len(updates), 2) self.assertEqual(updates[0].progress, 10) self.assertEqual(updates[0].mode, models.ProgressMode.PAGE) self.assertEqual(updates[1].progress, 20) self.assertEqual(updates[1].mode, models.ProgressMode.PERCENT) - self.readthrough.progress = -10 - self.assertRaises(ValidationError, self.readthrough.clean_fields) - update = self.readthrough.create_update() + readthrough.progress = -10 + self.assertRaises(ValidationError, readthrough.clean_fields) + update = readthrough.create_update() self.assertRaises(ValidationError, update.clean_fields) diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py index 177b2ad62..230c503b0 100644 --- a/bookwyrm/tests/models/test_user_model.py +++ b/bookwyrm/tests/models/test_user_model.py @@ -5,11 +5,13 @@ from django.test import TestCase import responses from bookwyrm import models -from bookwyrm.settings import DOMAIN +from bookwyrm.settings import USE_HTTPS, DOMAIN # pylint: disable=missing-class-docstring # pylint: disable=missing-function-docstring class User(TestCase): + protocol = "https://" if USE_HTTPS else "http://" + def setUp(self): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): self.user = models.User.objects.create_user( @@ -24,13 +26,14 @@ class User(TestCase): def test_computed_fields(self): """username instead of id here""" - expected_id = "https://%s/user/mouse" % DOMAIN + expected_id = f"{self.protocol}{DOMAIN}/user/mouse" self.assertEqual(self.user.remote_id, expected_id) - self.assertEqual(self.user.username, "mouse@%s" % DOMAIN) + self.assertEqual(self.user.username, f"mouse@{DOMAIN}") self.assertEqual(self.user.localname, "mouse") - self.assertEqual(self.user.shared_inbox, "https://%s/inbox" % DOMAIN) - self.assertEqual(self.user.inbox, "%s/inbox" % expected_id) - self.assertEqual(self.user.outbox, "%s/outbox" % expected_id) + self.assertEqual(self.user.shared_inbox, f"{self.protocol}{DOMAIN}/inbox") + self.assertEqual(self.user.inbox, f"{expected_id}/inbox") + self.assertEqual(self.user.outbox, f"{expected_id}/outbox") + self.assertEqual(self.user.followers_url, f"{expected_id}/followers") self.assertIsNotNone(self.user.key_pair.private_key) self.assertIsNotNone(self.user.key_pair.public_key) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py index ac57d8b3d..56ba844ad 100644 --- a/bookwyrm/tests/test_activitystreams.py +++ b/bookwyrm/tests/test_activitystreams.py @@ -8,6 +8,7 @@ from bookwyrm import activitystreams, models @patch("bookwyrm.activitystreams.ActivityStream.add_status") @patch("bookwyrm.activitystreams.BooksStream.add_book_statuses") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") +# pylint: disable=too-many-public-methods class Activitystreams(TestCase): """using redis to build activity streams""" @@ -286,3 +287,76 @@ class Activitystreams(TestCase): # yes book, yes audience result = activitystreams.BooksStream().get_statuses_for_user(self.local_user) self.assertEqual(list(result), [status]) + + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + def test_boost_to_another_timeline(self, *_): + """add a boost and deduplicate the boosted status on the timeline""" + status = models.Status.objects.create(user=self.local_user, content="hi") + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ): + boost = models.Boost.objects.create( + boosted_status=status, + user=self.another_user, + ) + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ) as mock: + activitystreams.add_status_on_create(models.Boost, boost, True) + self.assertTrue(mock.called) + call_args = mock.call_args + self.assertEqual(call_args[0][0], status) + self.assertEqual( + call_args[1]["stores"], ["{:d}-home".format(self.another_user.id)] + ) + + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + def test_boost_to_following_timeline(self, *_): + """add a boost and deduplicate the boosted status on the timeline""" + self.local_user.following.add(self.another_user) + status = models.Status.objects.create(user=self.local_user, content="hi") + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ): + boost = models.Boost.objects.create( + boosted_status=status, + user=self.another_user, + ) + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ) as mock: + activitystreams.add_status_on_create(models.Boost, boost, True) + self.assertTrue(mock.called) + call_args = mock.call_args + self.assertEqual(call_args[0][0], status) + self.assertTrue( + "{:d}-home".format(self.another_user.id) in call_args[1]["stores"] + ) + self.assertTrue( + "{:d}-home".format(self.local_user.id) in call_args[1]["stores"] + ) + + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + def test_boost_to_same_timeline(self, *_): + """add a boost and deduplicate the boosted status on the timeline""" + status = models.Status.objects.create(user=self.local_user, content="hi") + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ): + boost = models.Boost.objects.create( + boosted_status=status, + user=self.local_user, + ) + with patch( + "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + ) as mock: + activitystreams.add_status_on_create(models.Boost, boost, True) + self.assertTrue(mock.called) + call_args = mock.call_args + self.assertEqual(call_args[0][0], status) + self.assertEqual( + call_args[1]["stores"], ["{:d}-home".format(self.local_user.id)] + ) diff --git a/bookwyrm/tests/views/inbox/test_inbox_create.py b/bookwyrm/tests/views/inbox/test_inbox_create.py index 6e8917238..059d05223 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_create.py +++ b/bookwyrm/tests/views/inbox/test_inbox_create.py @@ -77,6 +77,33 @@ class InboxCreate(TestCase): views.inbox.activity_task(activity) self.assertEqual(models.Status.objects.count(), 1) + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_create_comment_with_reading_status(self, *_): + """the "it justs works" mode""" + datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_comment.json") + status_data = json.loads(datafile.read_bytes()) + status_data["readingStatus"] = "to-read" + + models.Edition.objects.create( + title="Test Book", remote_id="https://example.com/book/1" + ) + activity = self.create_json + activity["object"] = status_data + + with patch("bookwyrm.activitystreams.ActivityStream.add_status") as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) + + status = models.Comment.objects.get() + self.assertEqual(status.remote_id, "https://example.com/user/mouse/comment/6") + self.assertEqual(status.content, "commentary") + self.assertEqual(status.reading_status, "to-read") + self.assertEqual(status.user, self.local_user) + + # while we're here, lets ensure we avoid dupes + views.inbox.activity_task(activity) + self.assertEqual(models.Status.objects.count(), 1) + def test_create_status_remote_note_with_mention(self, _): """should only create it under the right circumstances""" self.assertFalse( diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index c5d86a12d..2cd50302f 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -280,49 +280,6 @@ class BookViews(TestCase): self.assertEqual(book.authors.first().name, "Sappho") self.assertEqual(book.authors.first(), book.parent_work.authors.first()) - @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") - def test_switch_edition(self, _): - """updates user's relationships to a book""" - work = models.Work.objects.create(title="test work") - edition1 = models.Edition.objects.create(title="first ed", parent_work=work) - edition2 = models.Edition.objects.create(title="second ed", parent_work=work) - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - shelf = models.Shelf.objects.create(name="Test Shelf", user=self.local_user) - models.ShelfBook.objects.create( - book=edition1, - user=self.local_user, - shelf=shelf, - ) - models.ReadThrough.objects.create(user=self.local_user, book=edition1) - - self.assertEqual(models.ShelfBook.objects.get().book, edition1) - self.assertEqual(models.ReadThrough.objects.get().book, edition1) - request = self.factory.post("", {"edition": edition2.id}) - request.user = self.local_user - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - views.switch_edition(request) - - self.assertEqual(models.ShelfBook.objects.get().book, edition2) - self.assertEqual(models.ReadThrough.objects.get().book, edition2) - - def test_editions_page(self): - """there are so many views, this just makes sure it LOADS""" - view = views.Editions.as_view() - request = self.factory.get("") - with patch("bookwyrm.views.books.is_api_request") as is_api: - is_api.return_value = False - result = view(request, self.work.id) - self.assertIsInstance(result, TemplateResponse) - result.render() - self.assertEqual(result.status_code, 200) - - request = self.factory.get("") - with patch("bookwyrm.views.books.is_api_request") as is_api: - is_api.return_value = True - result = view(request, self.work.id) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - def test_upload_cover_file(self): """add a cover via file upload""" self.assertFalse(self.book.cover) diff --git a/bookwyrm/tests/views/test_editions.py b/bookwyrm/tests/views/test_editions.py new file mode 100644 index 000000000..1bd23ae11 --- /dev/null +++ b/bookwyrm/tests/views/test_editions.py @@ -0,0 +1,126 @@ +""" 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 + +from bookwyrm import models, views +from bookwyrm.activitypub import ActivitypubResponse + + +class BookViews(TestCase): + """books books books""" + + def setUp(self): + """we need basic test data and mocks""" + self.factory = RequestFactory() + with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): + 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.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, + physical_format="paperback", + ) + + models.SiteSettings.objects.create() + + def test_editions_page(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Editions.as_view() + request = self.factory.get("") + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertTrue("paperback" in result.context_data["formats"]) + + def test_editions_page_filtered(self): + """editions view with filters""" + models.Edition.objects.create( + title="Fish", + physical_format="okay", + parent_work=self.work, + ) + view = views.Editions.as_view() + request = self.factory.get("") + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(len(result.context_data["editions"].object_list), 2) + self.assertEqual(len(result.context_data["formats"]), 2) + self.assertTrue("paperback" in result.context_data["formats"]) + self.assertTrue("okay" in result.context_data["formats"]) + + request = self.factory.get("", {"q": "fish"}) + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(len(result.context_data["editions"].object_list), 1) + + request = self.factory.get("", {"q": "okay"}) + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(len(result.context_data["editions"].object_list), 1) + + request = self.factory.get("", {"format": "okay"}) + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(len(result.context_data["editions"].object_list), 1) + + def test_editions_page_api(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Editions.as_view() + request = self.factory.get("") + with patch("bookwyrm.views.editions.is_api_request") as is_api: + is_api.return_value = True + result = view(request, self.work.id) + self.assertIsInstance(result, ActivitypubResponse) + self.assertEqual(result.status_code, 200) + + @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") + def test_switch_edition(self, _): + """updates user's relationships to a book""" + work = models.Work.objects.create(title="test work") + edition1 = models.Edition.objects.create(title="first ed", parent_work=work) + edition2 = models.Edition.objects.create(title="second ed", parent_work=work) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + shelf = models.Shelf.objects.create(name="Test Shelf", user=self.local_user) + models.ShelfBook.objects.create( + book=edition1, + user=self.local_user, + shelf=shelf, + ) + models.ReadThrough.objects.create(user=self.local_user, book=edition1) + + self.assertEqual(models.ShelfBook.objects.get().book, edition1) + self.assertEqual(models.ReadThrough.objects.get().book, edition1) + request = self.factory.post("", {"edition": edition2.id}) + request.user = self.local_user + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + views.switch_edition(request) + + self.assertEqual(models.ShelfBook.objects.get().book, edition2) + self.assertEqual(models.ReadThrough.objects.get().book, edition2) diff --git a/bookwyrm/tests/views/test_feed.py b/bookwyrm/tests/views/test_feed.py index 666c3e02b..e13dd7f8a 100644 --- a/bookwyrm/tests/views/test_feed.py +++ b/bookwyrm/tests/views/test_feed.py @@ -82,6 +82,27 @@ class FeedViews(TestCase): self.assertEqual(result.status_code, 404) + def test_status_page_not_found_wrong_user(self, *_): + """there are so many views, this just makes sure it LOADS""" + view = views.Status.as_view() + another_user = models.User.objects.create_user( + "rat@local.com", + "rat@rat.rat", + "password", + local=True, + localname="rat", + ) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + status = models.Status.objects.create(content="hi", user=another_user) + + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.feed.is_api_request") as is_api: + is_api.return_value = False + result = view(request, "mouse", status.id) + + self.assertEqual(result.status_code, 404) + def test_status_page_with_image(self, *_): """there are so many views, this just makes sure it LOADS""" view = views.Status.as_view() diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py index 988d8d4ad..d5e917c38 100644 --- a/bookwyrm/tests/views/test_list.py +++ b/bookwyrm/tests/views/test_list.py @@ -91,6 +91,52 @@ class ListViews(TestCase): result.render() self.assertEqual(result.status_code, 200) + def test_saved_lists_page(self): + """there are so many views, this just makes sure it LOADS""" + view = views.SavedLists.as_view() + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + booklist = models.List.objects.create( + name="Public list", user=self.local_user + ) + models.List.objects.create( + name="Private list", privacy="direct", user=self.local_user + ) + self.local_user.saved_lists.add(booklist) + request = self.factory.get("") + request.user = self.local_user + + result = view(request) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["lists"].object_list, [booklist]) + + def test_saved_lists_page_empty(self): + """there are so many views, this just makes sure it LOADS""" + view = views.SavedLists.as_view() + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): + models.List.objects.create(name="Public list", user=self.local_user) + models.List.objects.create( + name="Private list", privacy="direct", user=self.local_user + ) + request = self.factory.get("") + request.user = self.local_user + + result = view(request) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(len(result.context_data["lists"].object_list), 0) + + def test_saved_lists_page_logged_out(self): + """logged out saved lists""" + view = views.SavedLists.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = view(request) + self.assertEqual(result.status_code, 302) + def test_lists_create(self): """create list view""" view = views.Lists.as_view() @@ -328,15 +374,8 @@ class ListViews(TestCase): def test_user_lists_page_logged_out(self): """there are so many views, this just makes sure it LOADS""" view = views.UserLists.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - models.List.objects.create(name="Public list", user=self.local_user) - models.List.objects.create( - name="Private list", privacy="direct", user=self.local_user - ) request = self.factory.get("") request.user = self.anonymous_user result = view(request, self.local_user.username) - self.assertIsInstance(result, TemplateResponse) - result.render() - self.assertEqual(result.status_code, 200) + self.assertEqual(result.status_code, 302) diff --git a/bookwyrm/tests/views/test_reading.py b/bookwyrm/tests/views/test_reading.py index bebd9f5a9..61464bc7f 100644 --- a/bookwyrm/tests/views/test_reading.py +++ b/bookwyrm/tests/views/test_reading.py @@ -107,7 +107,7 @@ class ReadingViews(TestCase): { "post-status": True, "privacy": "followers", - "finish_date": "2020-01-07", + "finish_date": timezone.now().isoformat(), "id": readthrough.id, }, ) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index d4edee0b3..ff429e20f 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -303,6 +303,19 @@ class StatusViews(TestCase): 'openlibrary.org/search' "?q=arkady+strugatsky&mode=everything" % url, ) + url = "https://tech.lgbt/@bookwyrm" + self.assertEqual( + views.status.format_links(url), 'tech.lgbt/@bookwyrm' % url + ) + url = "https://users.speakeasy.net/~lion/nb/book.pdf" + self.assertEqual( + views.status.format_links(url), + 'users.speakeasy.net/~lion/nb/book.pdf' % url, + ) + url = "https://pkm.one/#/page/The%20Book%20which%20launched%20a%201000%20Note%20taking%20apps" + self.assertEqual( + views.status.format_links(url), '%s' % (url, url[8:]) + ) def test_to_markdown(self, *_): """this is mostly handled in other places, but nonetheless""" diff --git a/bookwyrm/tests/views/test_wellknown.py b/bookwyrm/tests/views/test_wellknown.py index 4a3eb579f..fcbcc12b7 100644 --- a/bookwyrm/tests/views/test_wellknown.py +++ b/bookwyrm/tests/views/test_wellknown.py @@ -51,6 +51,16 @@ class UserViews(TestCase): data = json.loads(result.getvalue()) self.assertEqual(data["subject"], "acct:mouse@local.com") + def test_webfinger_case_sensitivty(self): + """ensure that webfinger queries are not case sensitive""" + request = self.factory.get("", {"resource": "acct:MoUsE@local.com"}) + request.user = self.anonymous_user + + result = views.webfinger(request) + self.assertIsInstance(result, JsonResponse) + data = json.loads(result.getvalue()) + self.assertEqual(data["subject"], "acct:mouse@local.com") + def test_nodeinfo_pointer(self): """just tells you where nodeinfo is""" request = self.factory.get("") diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 4c85954bb..1dbd67a76 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -218,6 +218,7 @@ urlpatterns = [ # lists re_path(r"%s/lists/?$" % USER_PATH, views.UserLists.as_view(), name="user-lists"), re_path(r"^list/?$", views.Lists.as_view(), name="lists"), + re_path(r"^list/saved/?$", views.SavedLists.as_view(), name="saved-lists"), re_path(r"^list/(?P\d+)(.json)?/?$", views.List.as_view(), name="list"), re_path(r"^list/add-book/?$", views.list.add_book, name="list-add-book"), re_path( @@ -233,6 +234,8 @@ urlpatterns = [ re_path( r"^list/(?P\d+)/curate/?$", views.Curate.as_view(), name="list-curate" ), + re_path(r"^save-list/(?P\d+)/?$", views.save_list, name="list-save"), + re_path(r"^unsave-list/(?P\d+)/?$", views.unsave_list, name="list-unsave"), # User books re_path(r"%s/books/?$" % USER_PATH, views.Shelf.as_view(), name="user-shelves"), re_path( @@ -294,8 +297,10 @@ urlpatterns = [ name="redraft", ), # interact - re_path(r"^favorite/(?P\d+)/?$", views.Favorite.as_view()), - re_path(r"^unfavorite/(?P\d+)/?$", views.Unfavorite.as_view()), + re_path(r"^favorite/(?P\d+)/?$", views.Favorite.as_view(), name="fav"), + re_path( + r"^unfavorite/(?P\d+)/?$", views.Unfavorite.as_view(), name="unfav" + ), re_path(r"^boost/(?P\d+)/?$", views.Boost.as_view()), re_path(r"^unboost/(?P\d+)/?$", views.Unboost.as_view()), # books diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 15b55accb..f42049254 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -4,11 +4,12 @@ from .authentication import Login, Register, Logout from .authentication import ConfirmEmail, ConfirmEmailCode, resend_link from .author import Author, EditAuthor from .block import Block, unblock -from .books import Book, EditBook, ConfirmEditBook, Editions -from .books import upload_cover, add_description, switch_edition, resolve_book +from .books import Book, EditBook, ConfirmEditBook +from .books import upload_cover, add_description, resolve_book from .directory import Directory from .discover import Discover from .edit_user import EditUser, DeleteUser +from .editions import Editions, switch_edition from .federation import Federation, FederatedServer from .federation import AddFederatedServer, ImportServerBlocklist from .federation import block_server, unblock_server @@ -24,7 +25,8 @@ from .invite import ManageInvites, Invite, InviteRequest from .invite import ManageInviteRequests, ignore_invite_request from .isbn import Isbn from .landing import About, Home, Landing -from .list import Lists, List, Curate, UserLists +from .list import Lists, SavedLists, List, Curate, UserLists +from .list import save_list, unsave_list from .notifications import Notifications from .outbox import Outbox from .reading import edit_readthrough, create_readthrough diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 6cd0427c1..c25252959 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -24,7 +24,7 @@ from bookwyrm.settings import PAGE_LENGTH from .helpers import is_api_request, get_edition, privacy_filter -# pylint: disable= no-self-use +# pylint: disable=no-self-use class Book(View): """a book! this is the stuff""" @@ -62,7 +62,7 @@ class Book(View): queryset = queryset.filter(user=request.user, deleted=False) else: queryset = reviews.exclude(Q(content__isnull=True) | Q(content="")) - queryset = queryset.select_related("user") + queryset = queryset.select_related("user").order_by("-published_date") paginated = Paginator(queryset, PAGE_LENGTH) lists = privacy_filter( @@ -270,37 +270,6 @@ class ConfirmEditBook(View): return redirect("/book/%s" % book.id) -class Editions(View): - """list of editions""" - - def get(self, request, book_id): - """list of editions of a book""" - work = get_object_or_404(models.Work, id=book_id) - - if is_api_request(request): - return ActivitypubResponse(work.to_edition_list(**request.GET)) - filters = {} - - if request.GET.get("language"): - filters["languages__contains"] = [request.GET.get("language")] - if request.GET.get("format"): - filters["physical_format__iexact"] = request.GET.get("format") - - editions = work.editions.order_by("-edition_rank") - languages = set(sum([e.languages for e in editions], [])) - - paginated = Paginator(editions.filter(**filters), PAGE_LENGTH) - data = { - "editions": paginated.get_page(request.GET.get("page")), - "work": work, - "languages": languages, - "formats": set( - e.physical_format.lower() for e in editions if e.physical_format - ), - } - return TemplateResponse(request, "book/editions.html", data) - - @login_required @require_POST def upload_cover(request, book_id): @@ -363,33 +332,3 @@ def resolve_book(request): book = connector.get_or_create_book(remote_id) return redirect("book", book.id) - - -@login_required -@require_POST -@transaction.atomic -def switch_edition(request): - """switch your copy of a book to a different edition""" - edition_id = request.POST.get("edition") - new_edition = get_object_or_404(models.Edition, id=edition_id) - shelfbooks = models.ShelfBook.objects.filter( - book__parent_work=new_edition.parent_work, shelf__user=request.user - ) - for shelfbook in shelfbooks.all(): - with transaction.atomic(): - models.ShelfBook.objects.create( - created_date=shelfbook.created_date, - user=shelfbook.user, - shelf=shelfbook.shelf, - book=new_edition, - ) - shelfbook.delete() - - readthroughs = models.ReadThrough.objects.filter( - book__parent_work=new_edition.parent_work, user=request.user - ) - for readthrough in readthroughs.all(): - readthrough.book = new_edition - readthrough.save() - - return redirect("/book/%d" % new_edition.id) diff --git a/bookwyrm/views/editions.py b/bookwyrm/views/editions.py new file mode 100644 index 000000000..7615c497c --- /dev/null +++ b/bookwyrm/views/editions.py @@ -0,0 +1,99 @@ +""" the good stuff! the books! """ +from functools import reduce +import operator + +from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator +from django.db import transaction +from django.db.models import Q +from django.shortcuts import get_object_or_404, redirect +from django.template.response import TemplateResponse +from django.views import View +from django.views.decorators.http import require_POST + +from bookwyrm import models +from bookwyrm.activitypub import ActivitypubResponse +from bookwyrm.settings import PAGE_LENGTH +from .helpers import is_api_request + + +# pylint: disable=no-self-use +class Editions(View): + """list of editions""" + + def get(self, request, book_id): + """list of editions of a book""" + work = get_object_or_404(models.Work, id=book_id) + + if is_api_request(request): + return ActivitypubResponse(work.to_edition_list(**request.GET)) + filters = {} + + if request.GET.get("language"): + filters["languages__contains"] = [request.GET.get("language")] + if request.GET.get("format"): + filters["physical_format__iexact"] = request.GET.get("format") + + editions = work.editions.order_by("-edition_rank") + languages = set(sum(editions.values_list("languages", flat=True), [])) + + editions = editions.filter(**filters) + + query = request.GET.get("q") + if query: + searchable_array_fields = ["languages", "publishers"] + searchable_fields = [ + "title", + "physical_format", + "isbn_10", + "isbn_13", + "oclc_number", + "asin", + ] + search_filter_entries = [ + {f"{f}__icontains": query} for f in searchable_fields + ] + [{f"{f}__iexact": query} for f in searchable_array_fields] + editions = editions.filter( + reduce(operator.or_, (Q(**f) for f in search_filter_entries)) + ) + + paginated = Paginator(editions, PAGE_LENGTH) + data = { + "editions": paginated.get_page(request.GET.get("page")), + "work": work, + "languages": languages, + "formats": set( + e.physical_format.lower() for e in editions if e.physical_format + ), + } + return TemplateResponse(request, "book/editions.html", data) + + +@login_required +@require_POST +@transaction.atomic +def switch_edition(request): + """switch your copy of a book to a different edition""" + edition_id = request.POST.get("edition") + new_edition = get_object_or_404(models.Edition, id=edition_id) + shelfbooks = models.ShelfBook.objects.filter( + book__parent_work=new_edition.parent_work, shelf__user=request.user + ) + for shelfbook in shelfbooks.all(): + with transaction.atomic(): + models.ShelfBook.objects.create( + created_date=shelfbook.created_date, + user=shelfbook.user, + shelf=shelfbook.shelf, + book=new_edition, + ) + shelfbook.delete() + + readthroughs = models.ReadThrough.objects.filter( + book__parent_work=new_edition.parent_work, user=request.user + ) + for readthrough in readthroughs.all(): + readthrough.book = new_edition + readthrough.save() + + return redirect("/book/%d" % new_edition.id) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 7a46ca57d..d17de8f96 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -96,15 +96,11 @@ class Status(View): try: user = get_user_from_username(request.user, username) status = models.Status.objects.select_subclasses().get( - id=status_id, deleted=False + user=user, id=status_id, deleted=False ) except (ValueError, models.Status.DoesNotExist): return HttpResponseNotFound() - # the url should have the poster's username in it - if user != status.user: - return HttpResponseNotFound() - # make sure the user is authorized to see the status if not status.visible_to_user(request.user): return HttpResponseNotFound() diff --git a/bookwyrm/views/isbn.py b/bookwyrm/views/isbn.py index 12208a3d7..3055a3542 100644 --- a/bookwyrm/views/isbn.py +++ b/bookwyrm/views/isbn.py @@ -1,9 +1,11 @@ """ isbn search view """ +from django.core.paginator import Paginator from django.http import JsonResponse from django.template.response import TemplateResponse from django.views import View from bookwyrm.connectors import connector_manager +from bookwyrm.settings import PAGE_LENGTH from .helpers import is_api_request # pylint: disable= no-self-use @@ -17,8 +19,12 @@ class Isbn(View): if is_api_request(request): return JsonResponse([r.json() for r in book_results], safe=False) + paginated = Paginator(book_results, PAGE_LENGTH).get_page( + request.GET.get("page") + ) data = { - "results": book_results, + "results": [{"results": paginated}], "query": isbn, + "type": "book", } - return TemplateResponse(request, "isbn_search_results.html", data) + return TemplateResponse(request, "search/book.html", data) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 6e872434c..e6ef52ba5 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -63,6 +63,25 @@ class Lists(View): return redirect(book_list.local_path) +@method_decorator(login_required, name="dispatch") +class SavedLists(View): + """saved book list page""" + + def get(self, request): + """display book lists""" + # hide lists with no approved books + lists = request.user.saved_lists.order_by("-updated_date") + + paginated = Paginator(lists, 12) + data = { + "lists": paginated.get_page(request.GET.get("page")), + "list_form": forms.ListForm(), + "path": "/list", + } + return TemplateResponse(request, "lists/lists.html", data) + + +@method_decorator(login_required, name="dispatch") class UserLists(View): """a user's book list page""" @@ -116,7 +135,7 @@ class List(View): if direction == "descending": directional_sort_by = "-" + directional_sort_by - items = book_list.listitem_set + items = book_list.listitem_set.prefetch_related("user", "book", "book__authors") if sort_by == "rating": items = items.annotate( average_rating=Avg( @@ -224,6 +243,25 @@ class Curate(View): @require_POST +@login_required +def save_list(request, list_id): + """save a list""" + book_list = get_object_or_404(models.List, id=list_id) + request.user.saved_lists.add(book_list) + return redirect("list", list_id) + + +@require_POST +@login_required +def unsave_list(request, list_id): + """unsave a list""" + book_list = get_object_or_404(models.List, id=list_id) + request.user.saved_lists.remove(book_list) + return redirect("list", list_id) + + +@require_POST +@login_required def add_book(request): """put a book on a list""" book_list = get_object_or_404(models.List, id=request.POST.get("list")) @@ -273,6 +311,7 @@ def add_book(request): @require_POST +@login_required def remove_book(request, list_id): """remove a book from a list""" with transaction.atomic(): @@ -289,6 +328,7 @@ def remove_book(request, list_id): @require_POST +@login_required def set_book_position(request, list_item_id): """ Action for when the list user manually specifies a list position, takes diff --git a/bookwyrm/views/password.py b/bookwyrm/views/password.py index 18fcb02cd..6d202ce24 100644 --- a/bookwyrm/views/password.py +++ b/bookwyrm/views/password.py @@ -5,7 +5,7 @@ from django.core.exceptions import PermissionDenied from django.shortcuts import redirect from django.template.response import TemplateResponse from django.utils.decorators import method_decorator -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from django.views import View from bookwyrm import models diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py index 1c897ab38..9100e1d43 100644 --- a/bookwyrm/views/reading.py +++ b/bookwyrm/views/reading.py @@ -12,7 +12,7 @@ from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.http import require_POST -from bookwyrm import models +from bookwyrm import forms, models from .helpers import get_edition, handle_reading_status @@ -76,8 +76,17 @@ class ReadingStatus(View): # post about it (if you want) if request.POST.get("post-status"): - privacy = request.POST.get("privacy") - handle_reading_status(request.user, desired_shelf, book, privacy) + # is it a comment? + if request.POST.get("content"): + form = forms.CommentForm(request.POST) + if form.is_valid(): + form.save() + else: + # uh oh + raise Exception(form.errors) + else: + privacy = request.POST.get("privacy") + handle_reading_status(request.user, desired_shelf, book, privacy) return redirect(request.headers.get("Referer", "/")) diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index e9ad074d1..ba9f6a3c1 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -9,7 +9,7 @@ from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.utils.decorators import method_decorator -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from django.views import View from django.views.decorators.http import require_POST diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 651021b63..fe1dfda13 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -1,13 +1,17 @@ """ what are we here for if not for posting """ import re +from urllib.parse import urlparse + from django.contrib.auth.decorators import login_required +from django.core.validators import URLValidator +from django.core.exceptions import ValidationError from django.http import HttpResponseBadRequest 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 markdown import markdown +from markdown import markdown from bookwyrm import forms, models from bookwyrm.sanitize_html import InputHtmlParser from bookwyrm.settings import DOMAIN @@ -149,17 +153,54 @@ def find_mentions(content): def format_links(content): """detect and format links""" - return re.sub( - r'([^(href=")]|^|\()(https?:\/\/(%s([\w\.\-_\/+&\?=:;,@#])*))' % regex.DOMAIN, - r'\g<1>\g<3>', - content, - ) + validator = URLValidator() + formatted_content = "" + split_content = content.split() + + for index, potential_link in enumerate(split_content): + wrapped = _wrapped(potential_link) + if wrapped: + wrapper_close = potential_link[-1] + formatted_content += potential_link[0] + potential_link = potential_link[1:-1] + + try: + # raises an error on anything that's not a valid link + validator(potential_link) + + # use everything but the scheme in the presentation of the link + url = urlparse(potential_link) + link = url.netloc + url.path + url.params + if url.query != "": + link += "?" + url.query + if url.fragment != "": + link += "#" + url.fragment + + formatted_content += '%s' % (potential_link, link) + except (ValidationError, UnicodeError): + formatted_content += potential_link + + if wrapped: + formatted_content += wrapper_close + if index < len(split_content) - 1: + formatted_content += " " + + return formatted_content + + +def _wrapped(text): + """check if a line of text is wrapped""" + wrappers = [("(", ")"), ("[", "]"), ("{", "}")] + for wrapper in wrappers: + if text[0] == wrapper[0] and text[-1] == wrapper[-1]: + return True + return False def to_markdown(content): """catch links and convert to markdown""" - content = markdown(content) content = format_links(content) + content = markdown(content) # sanitize resulting html sanitizer = InputHtmlParser() sanitizer.feed(content) diff --git a/bookwyrm/views/user_admin.py b/bookwyrm/views/user_admin.py index 7cfefb0f4..3a9ea3392 100644 --- a/bookwyrm/views/user_admin.py +++ b/bookwyrm/views/user_admin.py @@ -13,7 +13,7 @@ from bookwyrm.settings import PAGE_LENGTH # pylint: disable= no-self-use @method_decorator(login_required, name="dispatch") @method_decorator( - permission_required("bookwyrm.moderate_users", raise_exception=True), + permission_required("bookwyrm.moderate_user", raise_exception=True), name="dispatch", ) class UserAdminList(View): diff --git a/bookwyrm/views/wellknown.py b/bookwyrm/views/wellknown.py index 2462c5a49..9c76beafa 100644 --- a/bookwyrm/views/wellknown.py +++ b/bookwyrm/views/wellknown.py @@ -20,7 +20,7 @@ def webfinger(request): username = resource.replace("acct:", "") try: - user = models.User.objects.get(username=username) + user = models.User.objects.get(username__iexact=username) except models.User.DoesNotExist: return HttpResponseNotFound("No account found") diff --git a/bw-dev b/bw-dev index a2f04bfb6..f103de205 100755 --- a/bw-dev +++ b/bw-dev @@ -126,6 +126,9 @@ case "$CMD" in populate_suggestions) runweb python manage.py populate_suggestions ;; + generate_thumbnails) + runweb python manage.py generateimages + ;; generate_preview_images) runweb python manage.py generate_preview_images $@ ;; @@ -171,6 +174,7 @@ case "$CMD" in echo " black" echo " populate_streams [--stream=]" echo " populate_suggestions" + echo " generate_thumbnails" echo " generate_preview_images [--all]" echo " copy_media_to_s3" echo " set_cors_to_s3 [cors file]" diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index 543d53559..d2d1bc5f3 100644 Binary files a/locale/de_DE/LC_MESSAGES/django.mo and b/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 6d6588843..397e18c28 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-27 19:11+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,67 +18,67 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 #, fuzzy #| msgid "A user with that username already exists." msgid "A user with this email already exists." msgstr "Dieser Benutzename ist bereits vergeben." -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "Ein Tag" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "Eine Woche" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "Ein Monat" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "Läuft nicht aus" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "%(count)d Benutzungen" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 #, fuzzy #| msgid "Unlisted" msgid "Unlimited" msgstr "Ungelistet" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 #, fuzzy #| msgid "Title" msgid "Book Title" msgstr "Titel" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 #, fuzzy #| msgid "Started reading" msgid "Ascending" msgstr "Zu lesen angefangen" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 #, fuzzy #| msgid "Started reading" msgid "Descending" @@ -94,29 +94,29 @@ msgstr "%(value)s ist keine gültige remote_id" msgid "%(value)s is not a valid username" msgstr "%(value)s ist kein gültiger Username" -#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "Username" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "Dieser Benutzename ist bereits vergeben." -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 #, fuzzy #| msgid "Title" msgid "Books Timeline" msgstr "Titel" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 #, fuzzy @@ -124,27 +124,27 @@ msgstr "Titel" msgid "Books" msgstr "Buch" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "Englisch" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "Spanisch" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "Französisch" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "Vereinfachtes Chinesisch" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 msgid "Traditional Chinese" msgstr "" @@ -239,7 +239,7 @@ msgid "Last edited by:" msgstr "Zuletzt bearbeitet von:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "Metadaten" @@ -251,9 +251,9 @@ msgid "Name:" msgstr "" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 #, fuzzy #| msgid "Separate multiple publishers with commas." msgid "Separate multiple values with commas." @@ -284,7 +284,7 @@ msgid "Openlibrary key:" msgstr "" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 #, fuzzy #| msgid "View on OpenLibrary" msgid "Inventaire ID:" @@ -300,17 +300,17 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Speichern" @@ -318,16 +318,13 @@ msgstr "Speichern" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "Abbrechen" @@ -365,7 +362,7 @@ msgid "Add Description" msgstr "Beschreibung hinzufügen" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Beschreibung:" @@ -461,24 +458,24 @@ msgid "ISBN:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "OCLC Nummer:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 #, fuzzy #| msgid "Add cover" msgid "Upload cover:" msgstr "Cover hinzufügen" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "Cover von URL laden:" @@ -496,144 +493,144 @@ msgstr "Editionen von %(book_title)s" msgid "Add Book" msgstr "Bücher hinzufügen" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "Buchinfo bestätigen" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "Existiert \"%(name)s\" bereits als Autor:in?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, fuzzy, python-format #| msgid "Start \"%(book_title)s\"" msgid "Author of %(book_title)s" msgstr "\"%(book_title)s\" beginnen" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "Neue:r Autor:in" -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "Neu als Autor:in erstellen: %(name)s" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "Ist das eine Edition eines vorhandenen Werkes?" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "Dies ist ein neues Werk." -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "Bestätigen" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "Zurück" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "Titel:" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "Untertitel:" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "Seriennummer:" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 #, fuzzy #| msgid "Pages:" msgid "Languages:" msgstr "Seiten:" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 #, fuzzy #| msgid "Published" msgid "Publisher:" msgstr "Veröffentlicht" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "Erstveröffentlichungsdatum:" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "Veröffentlichungsdatum:" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 #, fuzzy #| msgid "Author" msgid "Authors" msgstr "Autor*in" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, fuzzy, python-format #| msgid "Lists: %(username)s" msgid "Remove %(name)s" msgstr "Listen: %(username)s" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, fuzzy, python-format #| msgid "Lists: %(username)s" msgid "Author page for %(name)s" msgstr "Listen: %(username)s" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 #, fuzzy #| msgid "Edit Author" msgid "Add Authors:" msgstr "Autor*in editieren" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "Physikalische Eigenschaften" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "Seiten:" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "Buchidentifikatoren" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "" @@ -701,31 +698,37 @@ msgstr "bewertet" msgid "Progress Updates:" msgstr "Fortschrittsupdates:" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "Abgeschlossen" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "Zeige alle Updates" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "Dieses Fortschrittsupdate löschen" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "Angefangen" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "Lesedaten bearbeiten" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "Diese Lesedaten löschen" +#: bookwyrm/templates/book/search_filter.html:5 +#, fuzzy +#| msgid "Search Results" +msgid "Search editions" +msgstr "Suchergebnisse" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -1068,22 +1071,22 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "Hier sind noch keine Bücher! Versuche nach Büchern zu suchen um loszulegen" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 #, fuzzy #| msgid "Read" msgid "To Read" msgstr "Auf der Leseliste" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 #, fuzzy #| msgid "Start reading" msgid "Currently Reading" msgstr "Gerade lesend" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "Gelesen" @@ -1098,6 +1101,10 @@ msgstr "%(year)s Leseziel" msgid "Who to follow" msgstr "" +#: bookwyrm/templates/feed/suggested_users.html:5 +msgid "View directory" +msgstr "" + #: bookwyrm/templates/get_started/book_preview.html:6 #, fuzzy, python-format #| msgid "Want to Read \"%(book_title)s\"" @@ -1116,7 +1123,6 @@ msgid "Search for a book" msgstr "Nach einem Buch suchen" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "Keine Bücher für \"%(query)s\" gefunden" @@ -1278,7 +1284,7 @@ msgid "%(username)s's %(year)s Books" msgstr "%(username)ss %(year)s Bücher" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "Bücher importieren" @@ -1332,7 +1338,7 @@ msgstr "Import gestartet:" msgid "Import completed:" msgstr "Import abgeschlossen:" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "AUFGABE GESCHEITERT" @@ -1409,19 +1415,6 @@ msgstr "Zugiff verweigert" msgid "Sorry! This invite code is no longer valid." msgstr "Sorry! Dieser Einladecode ist mehr gültig." -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "Suchergebnisse" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "Suchergebnisse für \"%(query)s\"" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "Passende Bücher" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1567,6 +1560,10 @@ msgstr "%(site_name)s auf %(suppo msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm ist open source Software. Du kannst dich auf GitHub beteiligen oder etwas melden." +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1719,10 +1716,28 @@ msgstr "Keine passenden Bücher zu \"%(query)s\" gefunden" msgid "Suggest" msgstr "Vorschlagen" +#: bookwyrm/templates/lists/list_items.html:15 +#, fuzzy +#| msgid "Save" +msgid "Saved" +msgstr "Speichern" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "Deine Listen" +#: bookwyrm/templates/lists/lists.html:35 +#, fuzzy +#| msgid "Lists" +msgid "All Lists" +msgstr "Listen" + +#: bookwyrm/templates/lists/lists.html:39 +#, fuzzy +#| msgid "Create List" +msgid "Saved Lists" +msgstr "Liste erstellen" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "" @@ -2236,31 +2251,31 @@ msgstr "Aktivität" msgid "Create Announcement" msgstr "Ankündigungen" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 #, fuzzy #| msgid "Added:" msgid "Date added" msgstr "Hinzugefügt:" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 #, fuzzy #| msgid "reviewed" msgid "Preview" msgstr "bewertete" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 #, fuzzy #| msgid "Started" msgid "Start date" msgstr "Gestartet" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 #, fuzzy #| msgid "Edit read dates" msgid "End date" msgstr "Lesedaten bearbeiten" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2268,13 +2283,13 @@ msgstr "Lesedaten bearbeiten" msgid "Status" msgstr "" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 #, fuzzy #| msgid "Activity" msgid "active" msgstr "Aktivität" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 #, fuzzy #| msgid "Activity" msgid "inactive" @@ -2670,7 +2685,7 @@ msgid_plural "and %(remainder_count_display)s others" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 #, fuzzy #| msgid "Add cover" msgid "No cover" @@ -2709,24 +2724,24 @@ msgid "Some thoughts on the book" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "Fortschritt:" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: bookwyrm/templates/snippets/readthrough_form.html:22 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "Seiten" #: bookwyrm/templates/snippets/create_status/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: bookwyrm/templates/snippets/readthrough_form.html:23 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "Prozent" #: bookwyrm/templates/snippets/create_status/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "von %(pages)s Seiten" @@ -2757,6 +2772,7 @@ msgid "Include spoiler alert" msgstr "Spoileralarm aktivieren" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 #, fuzzy #| msgid "Comment" msgid "Comment:" @@ -2806,13 +2822,13 @@ msgstr "Diese Lesedaten löschen?" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "Du löscht diesen Leseforschritt und %(count)s zugehörige Fortschrittsupdates." -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 #, fuzzy #| msgid "Un-like status" msgid "Un-like" @@ -2926,9 +2942,7 @@ msgid "Goal privacy:" msgstr "Sichtbarkeit des Ziels" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "Posten" @@ -3005,21 +3019,47 @@ msgstr "Raten" msgid "Rate" msgstr "" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "\"%(book_title)s\" abschließen" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Zu lesen angefangen" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "Lesen abgeschlossen" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +#, fuzzy +#| msgid "Progress" +msgid "Update progress" +msgstr "Fortschritt" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "\"%(book_title)s\" beginnen" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "\"%(book_title)s\" auf Leseliste setzen" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "Fortschritt" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "Lesen abgeschlossen" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "Registrieren" @@ -3040,18 +3080,6 @@ msgstr "Buch importieren" msgid "Move book" msgstr "Deine Bücher" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -msgid "Finish \"%(book_title)s\"" -msgstr "\"%(book_title)s\" abschließen" - -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 -#, fuzzy -#| msgid "Progress" -msgid "Update progress" -msgstr "Fortschritt" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "Mehr Regale" @@ -3060,31 +3088,20 @@ msgstr "Mehr Regale" msgid "Start reading" msgstr "Zu lesen beginnen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "Lesen abschließen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "Auf Leseliste setzen" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, fuzzy, python-format #| msgid "Lists: %(username)s" msgid "Remove from %(name)s" msgstr "Listen: %(username)s" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "\"%(book_title)s\" beginnen" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "\"%(book_title)s\" auf Leseliste setzen" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -3123,13 +3140,13 @@ msgstr "Direktnachrichten mit %(username)s" msgid "rated %(book)s:" msgstr "Direktnachrichten mit %(username)s" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, fuzzy, python-format #| msgid "Editions of \"%(work_title)s\"" msgid "finished reading %(book)s" msgstr "Editionen von \"%(work_title)s\"" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, fuzzy, python-format #| msgid "Direct Messages with %(username)s" msgid "started reading %(book)s" @@ -3141,7 +3158,7 @@ msgstr "Direktnachrichten mit %(username)s" msgid "reviewed %(book)s" msgstr "Direktnachrichten mit %(username)s" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, fuzzy, python-format #| msgid "replied to your status" msgid "%(username)s wants to read %(book)s" @@ -3275,13 +3292,13 @@ msgstr "Regal bearbeiten" msgid "Update shelf" msgstr "Regal aktualisieren" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 #, fuzzy #| msgid "books" msgid "All books" msgstr "Bücher" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "Regal erstellen" @@ -3455,11 +3472,11 @@ msgstr "" msgid "Access level:" msgstr "" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "" @@ -3485,6 +3502,17 @@ msgstr "Dieser Benutzename ist bereits vergeben." msgid "A password reset link sent to %s" msgstr "" +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "" + +#~ msgid "Search Results for \"%(query)s\"" +#~ msgstr "Suchergebnisse für \"%(query)s\"" + +#~ msgid "Matching Books" +#~ msgstr "Passende Bücher" + #, fuzzy #~| msgid "Federated Servers" #~ msgid "Federated Timeline" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index ba475e53a..65c402b1f 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-27 19:11+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,59 +18,59 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 msgid "A user with this email already exists." msgstr "" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 msgid "Unlimited" msgstr "" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 msgid "Book Title" msgstr "" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Ascending" msgstr "" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 msgid "Descending" msgstr "" @@ -84,53 +84,53 @@ msgstr "" msgid "%(value)s is not a valid username" msgstr "" -#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 msgid "Books Timeline" msgstr "" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 msgid "Traditional Chinese" msgstr "" @@ -219,7 +219,7 @@ msgid "Last edited by:" msgstr "" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "" @@ -231,9 +231,9 @@ msgid "Name:" msgstr "" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 msgid "Separate multiple values with commas." msgstr "" @@ -262,7 +262,7 @@ msgid "Openlibrary key:" msgstr "" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 msgid "Inventaire ID:" msgstr "" @@ -276,17 +276,17 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "" @@ -294,16 +294,13 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "" @@ -339,7 +336,7 @@ msgid "Add Description" msgstr "" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "" @@ -422,22 +419,22 @@ msgid "ISBN:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 msgid "Upload cover:" msgstr "" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "" @@ -452,133 +449,133 @@ msgstr "" msgid "Add Book" msgstr "" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, python-format msgid "Author of %(book_title)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "" -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "" -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 msgid "Languages:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 msgid "Publisher:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 msgid "Authors" msgstr "" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, python-format msgid "Remove %(name)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, python-format msgid "Author page for %(name)s" msgstr "" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 msgid "Add Authors:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "" @@ -644,31 +641,35 @@ msgstr "" msgid "Progress Updates:" msgstr "" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "" +#: bookwyrm/templates/book/search_filter.html:5 +msgid "Search editions" +msgstr "" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -976,18 +977,18 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "To Read" msgstr "" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Currently Reading" msgstr "" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "" @@ -1002,6 +1003,10 @@ msgstr "" msgid "Who to follow" msgstr "" +#: bookwyrm/templates/feed/suggested_users.html:5 +msgid "View directory" +msgstr "" + #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format msgid "Have you read %(book_title)s?" @@ -1017,7 +1022,6 @@ msgid "Search for a book" msgstr "" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "" @@ -1165,7 +1169,7 @@ msgid "%(username)s's %(year)s Books" msgstr "" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "" @@ -1215,7 +1219,7 @@ msgstr "" msgid "Import completed:" msgstr "" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "" @@ -1290,19 +1294,6 @@ msgstr "" msgid "Sorry! This invite code is no longer valid." msgstr "" -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1442,6 +1433,10 @@ msgstr "" msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "" +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1581,10 +1576,22 @@ msgstr "" msgid "Suggest" msgstr "" +#: bookwyrm/templates/lists/list_items.html:15 +msgid "Saved" +msgstr "" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "" +#: bookwyrm/templates/lists/lists.html:35 +msgid "All Lists" +msgstr "" + +#: bookwyrm/templates/lists/lists.html:39 +msgid "Saved Lists" +msgstr "" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "" @@ -2049,23 +2056,23 @@ msgstr "" msgid "Create Announcement" msgstr "" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 msgid "Date added" msgstr "" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 msgid "Preview" msgstr "" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 msgid "Start date" msgstr "" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 msgid "End date" msgstr "" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2073,11 +2080,11 @@ msgstr "" msgid "Status" msgstr "" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "active" msgstr "" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "inactive" msgstr "" @@ -2418,7 +2425,7 @@ msgid_plural "and %(remainder_count_display)s others" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" msgstr "" @@ -2450,24 +2457,24 @@ msgid "Some thoughts on the book" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: bookwyrm/templates/snippets/readthrough_form.html:22 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: bookwyrm/templates/snippets/readthrough_form.html:23 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "" @@ -2496,6 +2503,7 @@ msgid "Include spoiler alert" msgstr "" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" msgstr "" @@ -2537,13 +2545,13 @@ msgstr "" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "" -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" msgstr "" @@ -2646,9 +2654,7 @@ msgid "Goal privacy:" msgstr "" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "" @@ -2723,21 +2729,45 @@ msgstr "" msgid "Rate" msgstr "" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +msgid "Update progress" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "" @@ -2754,16 +2784,6 @@ msgstr "" msgid "Move book" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -msgid "Finish \"%(book_title)s\"" -msgstr "" - -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 -msgid "Update progress" -msgstr "" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "" @@ -2772,30 +2792,19 @@ msgstr "" msgid "Start reading" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, python-format msgid "Remove from %(name)s" msgstr "" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -2830,12 +2839,12 @@ msgstr "" msgid "rated %(book)s:" msgstr "" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, python-format msgid "finished reading %(book)s" msgstr "" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, python-format msgid "started reading %(book)s" msgstr "" @@ -2845,7 +2854,7 @@ msgstr "" msgid "reviewed %(book)s" msgstr "" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, python-format msgid "%(username)s wants to read %(book)s" msgstr "" @@ -2969,11 +2978,11 @@ msgstr "" msgid "Update shelf" msgstr "" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 msgid "All books" msgstr "" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "" @@ -3128,11 +3137,11 @@ msgstr "" msgid "Access level:" msgstr "" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "" @@ -3153,3 +3162,8 @@ msgstr "" #, python-format msgid "A password reset link sent to %s" msgstr "" + +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "" diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index a7b3e1812..6881c1026 100644 Binary files a/locale/es/LC_MESSAGES/django.mo and b/locale/es/LC_MESSAGES/django.mo differ diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index d073a36c7..117102781 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,9 +8,9 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-29 18:01+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" -"Last-Translator: FULL NAME \n" +"Last-Translator: Reese Porter \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" @@ -18,59 +18,59 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 msgid "A user with this email already exists." msgstr "Ya existe un usuario con ese correo electrónico." -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "Un día" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "Una semana" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "Un mes" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "Nunca se vence" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "%(count)d usos" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 msgid "Unlimited" msgstr "Sin límite" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "Orden de la lista" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 msgid "Book Title" msgstr "Título" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "Calificación" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "Ordenar por" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Ascending" msgstr "Ascendente" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 msgid "Descending" msgstr "Descendente" @@ -84,53 +84,53 @@ 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:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "nombre de usuario" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "Ya existe un usuario con ese nombre." -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "Línea temporal de hogar" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "Hogar" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 msgid "Books Timeline" msgstr "Línea temporal de libros" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "Libros" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "Inglés" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "Aléman" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "Francés" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "Chino simplificado" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 msgid "Traditional Chinese" msgstr "Chino tradicional" @@ -219,7 +219,7 @@ msgid "Last edited by:" msgstr "Editado más recientemente por:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "Metadatos" @@ -231,9 +231,9 @@ msgid "Name:" msgstr "Nombre:" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 msgid "Separate multiple values with commas." msgstr "Separar varios valores con comas." @@ -262,7 +262,7 @@ msgid "Openlibrary key:" msgstr "Clave OpenLibrary:" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 msgid "Inventaire ID:" msgstr "ID Inventaire:" @@ -276,17 +276,17 @@ msgstr "Clave Goodreads:" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Guardar" @@ -294,16 +294,13 @@ msgstr "Guardar" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "Cancelar" @@ -339,7 +336,7 @@ msgid "Add Description" msgstr "Agregar descripción" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Descripción:" @@ -422,22 +419,22 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "Número OCLC:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "ASIN:" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 msgid "Upload cover:" msgstr "Subir portada:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "Agregar portada de url:" @@ -452,133 +449,133 @@ msgstr "Editar \"%(book_title)s\"" msgid "Add Book" msgstr "Agregar libro" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "Confirmar información de libro" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "¿Es \"%(name)s\" un autor ya existente?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, python-format msgid "Author of %(book_title)s" msgstr "Autor de %(book_title)s" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "Este es un autor nuevo" -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "Creando un autor nuevo: %(name)s" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "¿Es esta una edición de una obra ya existente?" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "Esta es una obra nueva" -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "Confirmar" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "Volver" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "Título:" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "Subtítulo:" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "Serie:" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "Número de serie:" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 msgid "Languages:" msgstr "Idiomas:" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 msgid "Publisher:" msgstr "Editorial:" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "Fecha de primera publicación:" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "Fecha de publicación:" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 msgid "Authors" msgstr "Autores" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, python-format msgid "Remove %(name)s" msgstr "Quitar %(name)s" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, python-format msgid "Author page for %(name)s" msgstr "Página de autor por %(name)s" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 msgid "Add Authors:" msgstr "Agregar Autores:" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "Juan Nadie, Natalia Natalia" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "Portada:" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "Propiedades físicas:" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "Formato:" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "Páginas:" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "Identificadores de libro" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "ID OpenLibrary:" @@ -644,31 +641,35 @@ msgstr "lo calificó con" msgid "Progress Updates:" msgstr "Actualizaciones de progreso:" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "terminado" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "Mostrar todas las actualizaciones" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "Eliminar esta actualización de progreso" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "empezado" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "Editar fechas de lectura" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "Eliminar estas fechas de lectura" +#: bookwyrm/templates/book/search_filter.html:5 +msgid "Search editions" +msgstr "Buscar ediciones" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -954,10 +955,8 @@ msgid "You have no messages right now." msgstr "No tienes ningún mensaje en este momento." #: bookwyrm/templates/feed/feed.html:22 -#, fuzzy, python-format -#| msgid "load 0 unread status(es)" msgid "load 0 unread status(es)" -msgstr "cargar 0 status(es) no leído(s)" +msgstr "cargar 0 status(es) no leído(s)" #: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" @@ -977,18 +976,18 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "¡No hay ningún libro aqui ahorita! Busca a un libro para empezar" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "To Read" msgstr "Para leer" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Currently Reading" msgstr "Leyendo actualmente" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "Leido" @@ -1003,6 +1002,10 @@ msgstr "%(year)s Meta de lectura" msgid "Who to follow" msgstr "A quién seguir" +#: bookwyrm/templates/feed/suggested_users.html:5 +msgid "View directory" +msgstr "Ver directorio" + #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format msgid "Have you read %(book_title)s?" @@ -1018,7 +1021,6 @@ msgid "Search for a book" msgstr "Buscar libros" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "No se encontró ningún libro correspondiente a \"%(query)s\"" @@ -1166,7 +1168,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/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "Importar libros" @@ -1216,7 +1218,7 @@ msgstr "Importación ha empezado:" msgid "Import completed:" msgstr "Importación ha terminado:" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "TAREA FALLÓ" @@ -1291,19 +1293,6 @@ msgstr "Permiso denegado" msgid "Sorry! This invite code is no longer valid." msgstr "¡Disculpa! Este código de invitación no queda válido." -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "Resultados de búsqueda" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "Resultados de búsqueda por \"%(query)s\"" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "Libros correspondientes" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1443,6 +1432,10 @@ msgstr "Apoyar %(site_name)s en % msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm es software de código abierto. Puedes contribuir o reportar problemas en GitHub." +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "Des-guardar" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1582,10 +1575,22 @@ msgstr "No se encontró ningún libro correspondiente a la búsqueda: \"%(query) msgid "Suggest" msgstr "Sugerir" +#: bookwyrm/templates/lists/list_items.html:15 +msgid "Saved" +msgstr "Guardado" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "Tus listas" +#: bookwyrm/templates/lists/lists.html:35 +msgid "All Lists" +msgstr "Todas las listas" + +#: bookwyrm/templates/lists/lists.html:39 +msgid "Saved Lists" +msgstr "Listas guardadas" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "Iniciar sesión" @@ -2050,23 +2055,23 @@ msgstr "Activ@:" msgid "Create Announcement" msgstr "Crear anuncio" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 msgid "Date added" msgstr "Fecha agregada" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 msgid "Preview" msgstr "Vista preliminar" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 msgid "Start date" msgstr "Fecha de inicio" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 msgid "End date" msgstr "Fecha final" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2074,11 +2079,11 @@ msgstr "Fecha final" msgid "Status" msgstr "Status" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "active" msgstr "activo" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "inactive" msgstr "inactivo" @@ -2419,7 +2424,7 @@ msgid_plural "and %(remainder_count_display)s others" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" msgstr "Sin portada" @@ -2451,24 +2456,24 @@ msgid "Some thoughts on the book" msgstr "Algunos pensamientos sobre el libro" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "Progreso:" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: 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/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: 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/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "de %(pages)s páginas" @@ -2497,6 +2502,7 @@ msgid "Include spoiler alert" msgstr "Incluir alerta de spoiler" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" msgstr "Comentario:" @@ -2538,13 +2544,13 @@ msgstr "¿Eliminar estas fechas de lectura?" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "Estás eliminando esta lectura y sus %(count)s actualizaciones de progreso asociados." -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "Me gusta" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" msgstr "Quitar me gusta" @@ -2647,9 +2653,7 @@ msgid "Goal privacy:" msgstr "Privacidad de meta:" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "Compartir con tu feed" @@ -2678,10 +2682,8 @@ msgid "page %(page)s of %(total_pages)s" msgstr "página %(page)s de %(total_pages)s" #: bookwyrm/templates/snippets/page_text.html:6 -#, fuzzy, python-format -#| msgid "page %(page)s" msgid "page %(page)s" -msgstr "página %(pages)s" +msgstr "página %(page)s" #: bookwyrm/templates/snippets/pagination.html:12 msgid "Previous" @@ -2725,21 +2727,45 @@ msgstr "Da una calificación" msgid "Rate" msgstr "Calificar" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "Terminar \"%(book_title)s\"" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Lectura se empezó" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "Lectura se terminó" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "(Opcional)" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +msgid "Update progress" +msgstr "Progreso de actualización" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "Empezar \"%(book_title)s\"" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "Quiero leer \"%(book_title)s\"" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "Progreso" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "Lectura se terminó" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "Inscribirse" @@ -2756,16 +2782,6 @@ msgstr "Importar libro" msgid "Move book" msgstr "Mover libro" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -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:45 -msgid "Update progress" -msgstr "Progreso de actualización" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "Más estantes" @@ -2774,30 +2790,19 @@ msgstr "Más estantes" msgid "Start reading" msgstr "Empezar leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "Terminar de leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "Quiero leer" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, python-format msgid "Remove from %(name)s" msgstr "Quitar de %(name)s" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "Empezar \"%(book_title)s\"" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "Quiero leer \"%(book_title)s\"" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -2832,12 +2837,12 @@ msgstr "citó a %(book)s" msgid "rated %(book)s:" msgstr "calificó %(book)s:" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, python-format msgid "finished reading %(book)s" msgstr "terminó de leer %(book)s" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, python-format msgid "started reading %(book)s" msgstr "empezó a leer %(book)s" @@ -2847,7 +2852,7 @@ msgstr "empezó a leer %(book)s" msgid "reviewed %(book)s" msgstr "reseñó a %(book)s" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, python-format msgid "%(username)s wants to read %(book)s" msgstr "%(username)s quiere leer %(book)s" @@ -2971,11 +2976,11 @@ msgstr "Editar estante" msgid "Update shelf" msgstr "Actualizar estante" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 msgid "All books" msgstr "Todos los libros" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "Crear estante" @@ -3130,11 +3135,11 @@ msgstr "Des-suspender usuario" msgid "Access level:" msgstr "Nivel de acceso:" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "Archivo excede el tamaño máximo: 10MB" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "%(title)s: %(subtitle)s" @@ -3156,6 +3161,17 @@ 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" +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "Actualizaciones de status de {obj.display_name}" + +#~ msgid "Search Results for \"%(query)s\"" +#~ msgstr "Resultados de búsqueda por \"%(query)s\"" + +#~ msgid "Matching Books" +#~ msgstr "Libros correspondientes" + #~ msgid "Local Timeline" #~ msgstr "Línea temporal local" diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 75ac69ebf..a28c903f6 100644 Binary files a/locale/fr_FR/LC_MESSAGES/django.mo and b/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index 1ab9157bd..81130aa34 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-27 19:11+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -18,59 +18,59 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 msgid "A user with this email already exists." msgstr "Cet email est déjà associé à un compte." -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "Un jour" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "Une semaine" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "Un mois" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "Sans expiration" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "%(count)d utilisations" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 msgid "Unlimited" msgstr "Sans limite" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "Ordre de la liste" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 msgid "Book Title" msgstr "Titre du livre" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "Note" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "Trier par" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Ascending" msgstr "Ordre croissant" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 msgid "Descending" msgstr "Ordre décroissant" @@ -84,55 +84,55 @@ msgstr "%(value)s n’est pas une remote_id valide." msgid "%(value)s is not a valid username" msgstr "%(value)s n’est pas un nom de compte valide." -#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "nom du compte :" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "Ce nom est déjà associé à un compte." -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "Mon fil d’actualité" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "Accueil" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 #, fuzzy #| msgid "Book Title" msgid "Books Timeline" msgstr "Titre du livre" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "Livres" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "English" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "Deutsch" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "Español" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "Français" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "简化字" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 #, fuzzy #| msgid "Additional info:" msgid "Traditional Chinese" @@ -223,7 +223,7 @@ msgid "Last edited by:" msgstr "Dernière modification par :" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "Métadonnées" @@ -235,9 +235,9 @@ msgid "Name:" msgstr "Nom :" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 msgid "Separate multiple values with commas." msgstr "Séparez plusieurs valeurs par une virgule." @@ -266,7 +266,7 @@ msgid "Openlibrary key:" msgstr "Clé Openlibrary :" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 msgid "Inventaire ID:" msgstr "Identifiant Inventaire :" @@ -280,17 +280,17 @@ msgstr "Clé Goodreads :" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "Enregistrer" @@ -298,16 +298,13 @@ msgstr "Enregistrer" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "Annuler" @@ -343,7 +340,7 @@ msgid "Add Description" msgstr "Ajouter une description" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "Description :" @@ -426,22 +423,22 @@ msgid "ISBN:" msgstr "ISBN :" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "Numéro OCLC :" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "ASIN :" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 msgid "Upload cover:" msgstr "Charger une couverture :" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "Charger la couverture depuis une URL :" @@ -456,133 +453,133 @@ msgstr "Modifier « %(book_title)s »" msgid "Add Book" msgstr "Ajouter un livre" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "Confirmer les informations de ce livre" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "Est‑ce que l’auteur/autrice « %(name)s » existe déjà ?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, python-format msgid "Author of %(book_title)s" msgstr "Auteur/autrice de %(book_title)s" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "Il s’agit d’un nouvel auteur ou d’une nouvelle autrice." -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "Création d’un nouvel auteur/autrice : %(name)s" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "Est‑ce l’édition d’un ouvrage existant ?" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "Il s’agit d’un nouvel ouvrage." -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "Confirmer" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "Retour" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "Titre :" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "Sous‑titre :" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "Série :" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "Numéro dans la série :" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 msgid "Languages:" msgstr "Langues :" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 msgid "Publisher:" msgstr "Éditeur :" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "Première date de publication :" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "Date de publication :" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 msgid "Authors" msgstr "Auteurs ou autrices" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, python-format msgid "Remove %(name)s" msgstr "Retirer %(name)s" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, python-format msgid "Author page for %(name)s" msgstr "Page de %(name)s" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 msgid "Add Authors:" msgstr "Ajouter des auteurs ou autrices :" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "Claude Dupont, Dominique Durand" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "Couverture" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "Propriétés physiques" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "Format :" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "Pages :" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "Identifiants du livre" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "ISBN 13 :" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "ISBN 10 :" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "Identifiant Openlibrary :" @@ -648,31 +645,37 @@ msgstr "l’a noté" msgid "Progress Updates:" msgstr "Progression :" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "terminé" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "Montrer toutes les progressions" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "Supprimer cette mise à jour" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "commencé" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "Modifier les date de lecture" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "Supprimer ces dates de lecture" +#: bookwyrm/templates/book/search_filter.html:5 +#, fuzzy +#| msgid "Search Results" +msgid "Search editions" +msgstr "Résultats de recherche" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -987,18 +990,18 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "Aucun livre ici pour l’instant ! Cherchez un livre pour commencer" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "To Read" msgstr "À lire" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Currently Reading" msgstr "Lectures en cours" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "Lu" @@ -1013,6 +1016,12 @@ msgstr "Défi lecture pour %(year)s" msgid "Who to follow" msgstr "À qui s’abonner" +#: bookwyrm/templates/feed/suggested_users.html:5 +#, fuzzy +#| msgid "Directory" +msgid "View directory" +msgstr "Répertoire" + #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format msgid "Have you read %(book_title)s?" @@ -1028,7 +1037,6 @@ msgid "Search for a book" msgstr "Chercher un livre" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "Aucun livre trouvé pour « %(query)s »" @@ -1176,7 +1184,7 @@ msgid "%(username)s's %(year)s Books" msgstr "Livres de %(username)s en %(year)s" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "Importer des livres" @@ -1228,7 +1236,7 @@ msgstr "Début de l’importation :" msgid "Import completed:" msgstr "Fin de l’importation :" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "la tâche a échoué" @@ -1305,19 +1313,6 @@ msgstr "Autorisation refusée" msgid "Sorry! This invite code is no longer valid." msgstr "Cette invitation n’est plus valide ; désolé !" -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "Résultats de recherche" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "Résultats de recherche pour « %(query)s »" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "Livres correspondants" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1457,6 +1452,10 @@ msgstr "Soutenez %(site_name)s avec GitHub." msgstr "BookWyrm est un logiciel libre. Vous pouvez contribuer ou faire des rapports de bogues via GitHub." +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1596,10 +1595,28 @@ msgstr "Aucun livre trouvé pour la requête « %(query)s »" msgid "Suggest" msgstr "Suggérer" +#: bookwyrm/templates/lists/list_items.html:15 +#, fuzzy +#| msgid "Save" +msgid "Saved" +msgstr "Enregistrer" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "Vos listes" +#: bookwyrm/templates/lists/lists.html:35 +#, fuzzy +#| msgid "Lists" +msgid "All Lists" +msgstr "Listes" + +#: bookwyrm/templates/lists/lists.html:39 +#, fuzzy +#| msgid "Create List" +msgid "Saved Lists" +msgstr "Créer une liste" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "Connexion" @@ -2071,23 +2088,23 @@ msgstr "Active :" msgid "Create Announcement" msgstr "Ajouter une annonce" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 msgid "Date added" msgstr "Date d’ajout" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 msgid "Preview" msgstr "Aperçu" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 msgid "Start date" msgstr "Date de début" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 msgid "End date" msgstr "Date de fin" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2095,11 +2112,11 @@ msgstr "Date de fin" msgid "Status" msgstr "Statut" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "active" msgstr "active" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "inactive" msgstr "inactive" @@ -2440,7 +2457,7 @@ msgid_plural "and %(remainder_count_display)s others" msgstr[0] "" msgstr[1] "" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" msgstr "Pas de couverture" @@ -2473,24 +2490,24 @@ msgid "Some thoughts on the book" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "Progression :" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: bookwyrm/templates/snippets/readthrough_form.html:22 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "pages" #: bookwyrm/templates/snippets/create_status/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: bookwyrm/templates/snippets/readthrough_form.html:23 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "pourcent" #: bookwyrm/templates/snippets/create_status/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "sur %(pages)s pages" @@ -2519,6 +2536,7 @@ msgid "Include spoiler alert" msgstr "Afficher une alerte spoiler" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" msgstr "Commentaire :" @@ -2562,13 +2580,13 @@ msgstr "Supprimer ces dates de lecture ?" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "Vous avez supprimé ce résumé et ses %(count)s progressions associées." -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "Ajouter aux favoris" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" msgstr "Retirer des favoris" @@ -2675,9 +2693,7 @@ msgid "Goal privacy:" msgstr "Confidentialité du défi :" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "Publier sur le fil d’actualité" @@ -2752,21 +2768,45 @@ msgstr "Laisser une note" msgid "Rate" msgstr "Noter" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "Terminer « %(book_title)s »" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "Lecture commencée le" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "Lecture terminée le" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +msgid "Update progress" +msgstr "Progression de la mise à jour" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "Commencer « %(book_title)s »" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "Ajouter « %(book_title)s » aux envies de lecture" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "Progression" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "Lecture terminée le" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "S’enregistrer" @@ -2783,16 +2823,6 @@ msgstr "Importer le livre" msgid "Move book" msgstr "Déplacer le livre" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -msgid "Finish \"%(book_title)s\"" -msgstr "Terminer « %(book_title)s »" - -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 -msgid "Update progress" -msgstr "Progression de la mise à jour" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "Plus d’étagères" @@ -2801,30 +2831,19 @@ msgstr "Plus d’étagères" msgid "Start reading" msgstr "Commencer la lecture" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "Terminer la lecture" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "Je veux le lire" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, python-format msgid "Remove from %(name)s" msgstr "Retirer de %(name)s" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "Commencer « %(book_title)s »" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "Ajouter « %(book_title)s » aux envies de lecture" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -2862,13 +2881,13 @@ msgstr "Signalé par %(username)s" msgid "rated %(book)s:" msgstr "Créée par %(username)s" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, fuzzy, python-format #| msgid "Editions of \"%(work_title)s\"" msgid "finished reading %(book)s" msgstr "Éditions de « %(work_title)s »" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, fuzzy, python-format #| msgid "Created by %(username)s" msgid "started reading %(book)s" @@ -2880,7 +2899,7 @@ msgstr "Créée par %(username)s" msgid "reviewed %(book)s" msgstr "Créée par %(username)s" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, fuzzy, python-format #| msgid "replied to %(username)s's quote" msgid "%(username)s wants to read %(book)s" @@ -3007,11 +3026,11 @@ msgstr "Modifier l’étagère" msgid "Update shelf" msgstr "Mettre l’étagère à jour" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 msgid "All books" msgstr "Tous les livres" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "Créer une étagère" @@ -3169,11 +3188,11 @@ msgstr "Rétablir le compte" msgid "Access level:" msgstr "Niveau d’accès :" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "Ce fichier dépasse la taille limite : 10 Mo" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" @@ -3195,6 +3214,17 @@ msgstr "Aucun compte avec cette adresse email n’a été trouvé." msgid "A password reset link sent to %s" msgstr "Un lien de réinitialisation a été envoyé à %s." +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "" + +#~ msgid "Search Results for \"%(query)s\"" +#~ msgstr "Résultats de recherche pour « %(query)s »" + +#~ msgid "Matching Books" +#~ msgstr "Livres correspondants" + #~ msgid "Local Timeline" #~ msgstr "Fil d’actualité local" diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index dbe69686f..bfcd3d019 100644 Binary files a/locale/zh_Hans/LC_MESSAGES/django.mo and b/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 547126495..df3ee019e 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-27 19:11+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -18,59 +18,59 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 msgid "A user with this email already exists." msgstr "已经存在使用该邮箱的用户。" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "一天" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "一周" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "一个月" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "永不失效" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "%(count)d 次使用" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 msgid "Unlimited" msgstr "不受限" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "列表顺序" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 msgid "Book Title" msgstr "书名" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "评价" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "排序方式" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Ascending" msgstr "升序" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 msgid "Descending" msgstr "降序" @@ -84,53 +84,53 @@ msgstr "%(value)s 不是有效的 remote_id" msgid "%(value)s is not a valid username" msgstr "%(value)s 不是有效的用户名" -#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "用户名" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "已经存在使用该用户名的用户。" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "主页时间线" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "主页" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 msgid "Books Timeline" msgstr "书目时间线" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "书目" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "English(英语)" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "Deutsch(德语)" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "Español(西班牙语)" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "Français(法语)" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "简体中文" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 msgid "Traditional Chinese" msgstr "繁體中文(繁体中文)" @@ -219,7 +219,7 @@ msgid "Last edited by:" msgstr "最后编辑人:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "元数据" @@ -231,9 +231,9 @@ msgid "Name:" msgstr "名称:" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 msgid "Separate multiple values with commas." msgstr "请用英文逗号(,)分隔多个值。" @@ -262,7 +262,7 @@ msgid "Openlibrary key:" msgstr "Openlibrary key:" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 msgid "Inventaire ID:" msgstr "Inventaire ID:" @@ -276,17 +276,17 @@ msgstr "Goodreads key:" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "保存" @@ -294,16 +294,13 @@ msgstr "保存" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "取消" @@ -338,7 +335,7 @@ msgid "Add Description" msgstr "添加描述" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "描述:" @@ -421,22 +418,22 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "OCLC 号:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "ASIN:" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 msgid "Upload cover:" msgstr "上传封面:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "从网址加载封面:" @@ -451,133 +448,133 @@ msgstr "编辑《%(book_title)s》" msgid "Add Book" msgstr "添加书目" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "确认书目信息" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "“%(name)s” 是已存在的作者吗?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, python-format msgid "Author of %(book_title)s" msgstr "%(book_title)s 的作者" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "这是一位新的作者" -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "正在创建新的作者: %(name)s" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "这是已存在的作品的一个版本吗?" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "这是一个新的作品。" -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "确认" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "返回" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "标题:" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "副标题:" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "系列:" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "系列编号:" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 msgid "Languages:" msgstr "语言:" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 msgid "Publisher:" msgstr "出版社:" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "初版时间:" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "出版时间:" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 msgid "Authors" msgstr "作者" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, python-format msgid "Remove %(name)s" msgstr "移除 %(name)s" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, python-format msgid "Author page for %(name)s" msgstr "%(name)s 的作者页面" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 msgid "Add Authors:" msgstr "添加作者:" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "张三, 李四" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "封面" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "实体性质" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "格式:" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "页数:" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "书目标识号" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "Openlibrary ID:" @@ -643,31 +640,37 @@ msgstr "评价了" msgid "Progress Updates:" msgstr "进度更新:" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "已完成" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "显示所有更新" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "删除此进度更新" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "已开始" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "编辑阅读日期" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "删除这些阅读日期" +#: bookwyrm/templates/book/search_filter.html:5 +#, fuzzy +#| msgid "Search Results" +msgid "Search editions" +msgstr "搜索结果" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -973,18 +976,18 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "现在这里还没有任何书目!尝试着从搜索某本书开始吧" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "To Read" msgstr "想读" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Currently Reading" msgstr "在读" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "读过" @@ -999,6 +1002,12 @@ msgstr "%(year)s 阅读目标" msgid "Who to follow" msgstr "可以关注的人" +#: bookwyrm/templates/feed/suggested_users.html:5 +#, fuzzy +#| msgid "Directory" +msgid "View directory" +msgstr "目录" + #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format msgid "Have you read %(book_title)s?" @@ -1014,7 +1023,6 @@ msgid "Search for a book" msgstr "搜索书目" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "没有找到 \"%(query)s\" 的书目" @@ -1162,7 +1170,7 @@ msgid "%(username)s's %(year)s Books" msgstr "%(username)s 在 %(year)s 的书目" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "导入书目" @@ -1212,7 +1220,7 @@ msgstr "导入开始:" msgid "Import completed:" msgstr "导入完成:" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "任务失败" @@ -1287,19 +1295,6 @@ msgstr "没有权限" msgid "Sorry! This invite code is no longer valid." msgstr "抱歉!此邀请码已不再有效。" -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "搜索结果" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "\"%(query)s\" 的搜索结果" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "匹配的书目" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1439,6 +1434,10 @@ msgstr "在 %(support_title)s msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm 是开源软件。你可以在 GitHub 贡献或报告问题。" +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1578,10 +1577,28 @@ msgstr "没有符合 “%(query)s” 请求的书目" msgid "Suggest" msgstr "推荐" +#: bookwyrm/templates/lists/list_items.html:15 +#, fuzzy +#| msgid "Save" +msgid "Saved" +msgstr "保存" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "你的列表" +#: bookwyrm/templates/lists/lists.html:35 +#, fuzzy +#| msgid "Lists" +msgid "All Lists" +msgstr "列表" + +#: bookwyrm/templates/lists/lists.html:39 +#, fuzzy +#| msgid "Create List" +msgid "Saved Lists" +msgstr "创建列表" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "登录" @@ -1791,8 +1808,9 @@ msgid "boosted your status" msgstr "转发了你的 状态" #: bookwyrm/templates/notifications.html:121 -#, python-format -msgid " added %(book_title)s to your list “%(list_name)s”" +#, fuzzy, python-format +#| msgid " added %(book_title)s to your list “%(list_name)s”" +msgid " added %(book_title)s to your list \"%(list_name)s\"" msgstr " 添加了 %(book_title)s 到你的列表 “%(list_name)s”" #: bookwyrm/templates/notifications.html:123 @@ -2046,23 +2064,23 @@ msgstr "活跃:" msgid "Create Announcement" msgstr "创建公告" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 msgid "Date added" msgstr "添加日期:" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 msgid "Preview" msgstr "预览" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 msgid "Start date" msgstr "开始日期" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 msgid "End date" msgstr "结束日期" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2070,11 +2088,11 @@ msgstr "结束日期" msgid "Status" msgstr "状态" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "active" msgstr "活跃" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "inactive" msgstr "停用" @@ -2414,7 +2432,7 @@ msgid "and %(remainder_count_display)s other" msgid_plural "and %(remainder_count_display)s others" msgstr[0] "与其它 %(remainder_count_display)s 位" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" msgstr "没有封面" @@ -2446,24 +2464,24 @@ msgid "Some thoughts on the book" msgstr "对书的一些看法" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "进度:" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: bookwyrm/templates/snippets/readthrough_form.html:22 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "页数" #: bookwyrm/templates/snippets/create_status/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: bookwyrm/templates/snippets/readthrough_form.html:23 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "百分比" #: bookwyrm/templates/snippets/create_status/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "全书 %(pages)s 页" @@ -2492,6 +2510,7 @@ msgid "Include spoiler alert" msgstr "加入剧透警告" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" msgstr "评论:" @@ -2533,13 +2552,13 @@ msgstr "删除这些阅读日期吗?" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "你正要删除这篇阅读经过以及与之相关的 %(count)s 次进度更新。" -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "喜欢" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" msgstr "取消喜欢" @@ -2638,9 +2657,7 @@ msgid "Goal privacy:" msgstr "目标隐私:" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "发布到消息流中" @@ -2715,21 +2732,45 @@ msgstr "留下评价" msgid "Rate" msgstr "评价" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "完成《%(book_title)s》" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "已开始阅读" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "已完成阅读" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +msgid "Update progress" +msgstr "更新进度" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "开始《%(book_title)s》" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "想要阅读《%(book_title)s》" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "进度" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "已完成阅读" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "注册" @@ -2746,16 +2787,6 @@ msgstr "导入书目" msgid "Move book" msgstr "移动书目" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -msgid "Finish \"%(book_title)s\"" -msgstr "完成《%(book_title)s》" - -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 -msgid "Update progress" -msgstr "更新进度" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "更多书架" @@ -2764,30 +2795,19 @@ msgstr "更多书架" msgid "Start reading" msgstr "开始阅读" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "完成阅读" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "想要阅读" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, python-format msgid "Remove from %(name)s" msgstr "从 %(name)s 移除" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "开始《%(book_title)s》" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "想要阅读《%(book_title)s》" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -2814,7 +2834,6 @@ msgstr "回复了 %(username)s%(username)s" msgid "quoted %(book)s" msgstr "引用了 %(book)s" @@ -2823,12 +2842,12 @@ msgstr "引用了 %(book)s" msgid "rated %(book)s:" msgstr "为 %(book)s 打了分:" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, python-format msgid "finished reading %(book)s" msgstr "完成阅读 %(book)s" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, python-format msgid "started reading %(book)s" msgstr "开始阅读 %(book)s" @@ -2838,7 +2857,7 @@ msgstr "开始阅读 %(book)s" msgid "reviewed %(book)s" msgstr "为 %(book)s 撰写了书评" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, python-format msgid "%(username)s wants to read %(book)s" msgstr "%(username)s 想要阅读 %(book)s" @@ -2960,11 +2979,11 @@ msgstr "编辑书架" msgid "Update shelf" msgstr "更新书架" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 msgid "All books" msgstr "所有书目" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "创建书架" @@ -3117,11 +3136,11 @@ msgstr "取消停用用户" msgid "Access level:" msgstr "访问级别:" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "文件超过了最大大小: 10MB" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" @@ -3143,6 +3162,17 @@ msgstr "没有找到使用该邮箱的用户。" msgid "A password reset link sent to %s" msgstr "密码重置连接已发送给 %s" +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "" + +#~ msgid "Search Results for \"%(query)s\"" +#~ msgstr "\"%(query)s\" 的搜索结果" + +#~ msgid "Matching Books" +#~ msgstr "匹配的书目" + #~ msgid "Local Timeline" #~ msgstr "本地时间线" diff --git a/locale/zh_Hant/LC_MESSAGES/django.mo b/locale/zh_Hant/LC_MESSAGES/django.mo index a1075ef48..0ee84d693 100644 Binary files a/locale/zh_Hant/LC_MESSAGES/django.mo and b/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 70caf596e..c8224be61 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-13 02:21+0000\n" +"POT-Creation-Date: 2021-08-27 19:11+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -18,59 +18,59 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: bookwyrm/forms.py:232 +#: bookwyrm/forms.py:233 msgid "A user with this email already exists." msgstr "已經存在使用該郵箱的使用者。" -#: bookwyrm/forms.py:246 +#: bookwyrm/forms.py:247 msgid "One Day" msgstr "一天" -#: bookwyrm/forms.py:247 +#: bookwyrm/forms.py:248 msgid "One Week" msgstr "一週" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:249 msgid "One Month" msgstr "一個月" -#: bookwyrm/forms.py:249 +#: bookwyrm/forms.py:250 msgid "Does Not Expire" msgstr "永不失效" -#: bookwyrm/forms.py:254 +#: bookwyrm/forms.py:255 #, python-format msgid "%(count)d uses" msgstr "%(count)d 次使用" -#: bookwyrm/forms.py:257 +#: bookwyrm/forms.py:258 msgid "Unlimited" msgstr "不受限" -#: bookwyrm/forms.py:307 +#: bookwyrm/forms.py:308 msgid "List Order" msgstr "列表順序" -#: bookwyrm/forms.py:308 +#: bookwyrm/forms.py:309 msgid "Book Title" msgstr "書名" -#: bookwyrm/forms.py:309 +#: bookwyrm/forms.py:310 #: bookwyrm/templates/snippets/create_status/review.html:25 #: bookwyrm/templates/user/shelf/shelf.html:85 #: bookwyrm/templates/user/shelf/shelf.html:116 msgid "Rating" msgstr "評價" -#: bookwyrm/forms.py:311 bookwyrm/templates/lists/list.html:107 +#: bookwyrm/forms.py:312 bookwyrm/templates/lists/list.html:107 msgid "Sort By" msgstr "排序方式" -#: bookwyrm/forms.py:315 +#: bookwyrm/forms.py:316 msgid "Ascending" msgstr "升序" -#: bookwyrm/forms.py:316 +#: bookwyrm/forms.py:317 msgid "Descending" msgstr "降序" @@ -84,55 +84,55 @@ msgstr "%(value)s 不是有效的 remote_id" msgid "%(value)s is not a valid username" msgstr "%(value)s 不是有效的使用者名稱" -#: bookwyrm/models/fields.py:174 bookwyrm/templates/layout.html:164 +#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:164 msgid "username" msgstr "使用者名稱" -#: bookwyrm/models/fields.py:179 +#: bookwyrm/models/fields.py:186 msgid "A user with that username already exists." msgstr "已經存在使用該名稱的使用者。" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home Timeline" msgstr "主頁時間線" -#: bookwyrm/settings.py:123 +#: bookwyrm/settings.py:124 msgid "Home" msgstr "主頁" -#: bookwyrm/settings.py:124 +#: bookwyrm/settings.py:125 #, fuzzy #| msgid "Book Title" msgid "Books Timeline" msgstr "書名" -#: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 +#: bookwyrm/settings.py:125 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 #: bookwyrm/templates/user/layout.html:81 msgid "Books" msgstr "書目" -#: bookwyrm/settings.py:170 +#: bookwyrm/settings.py:171 msgid "English" msgstr "English(英語)" -#: bookwyrm/settings.py:171 +#: bookwyrm/settings.py:172 msgid "German" msgstr "Deutsch(德語)" -#: bookwyrm/settings.py:172 +#: bookwyrm/settings.py:173 msgid "Spanish" msgstr "Español(西班牙語)" -#: bookwyrm/settings.py:173 +#: bookwyrm/settings.py:174 msgid "French" msgstr "Français(法語)" -#: bookwyrm/settings.py:174 +#: bookwyrm/settings.py:175 msgid "Simplified Chinese" msgstr "簡體中文" -#: bookwyrm/settings.py:175 +#: bookwyrm/settings.py:176 #, fuzzy #| msgid "Tranditional Chinese" msgid "Traditional Chinese" @@ -225,7 +225,7 @@ msgid "Last edited by:" msgstr "最後編輯者:" #: bookwyrm/templates/author/edit_author.html:31 -#: bookwyrm/templates/book/edit_book.html:117 +#: bookwyrm/templates/book/edit_book.html:124 msgid "Metadata" msgstr "元資料" @@ -237,9 +237,9 @@ msgid "Name:" msgstr "名稱:" #: bookwyrm/templates/author/edit_author.html:43 -#: bookwyrm/templates/book/edit_book.html:162 -#: bookwyrm/templates/book/edit_book.html:171 -#: bookwyrm/templates/book/edit_book.html:214 +#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:221 msgid "Separate multiple values with commas." msgstr "請用逗號(,)分隔多個值。" @@ -268,7 +268,7 @@ msgid "Openlibrary key:" msgstr "Openlibrary key:" #: bookwyrm/templates/author/edit_author.html:89 -#: bookwyrm/templates/book/edit_book.html:293 +#: bookwyrm/templates/book/edit_book.html:300 msgid "Inventaire ID:" msgstr "Inventaire ID:" @@ -282,17 +282,17 @@ msgstr "Goodreads key:" #: bookwyrm/templates/author/edit_author.html:116 #: bookwyrm/templates/book/book.html:141 -#: bookwyrm/templates/book/edit_book.html:321 -#: bookwyrm/templates/book/readthrough.html:77 +#: bookwyrm/templates/book/edit_book.html:328 +#: bookwyrm/templates/book/readthrough.html:76 +#: bookwyrm/templates/lists/bookmark_button.html:15 #: bookwyrm/templates/lists/form.html:42 #: bookwyrm/templates/preferences/edit_user.html:78 #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 #: bookwyrm/templates/settings/site.html:108 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/layout.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:42 #: bookwyrm/templates/user_admin/user_moderation_actions.html:45 msgid "Save" msgstr "儲存" @@ -300,16 +300,13 @@ msgstr "儲存" #: bookwyrm/templates/author/edit_author.html:117 #: bookwyrm/templates/book/book.html:142 bookwyrm/templates/book/book.html:191 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit_book.html:322 -#: bookwyrm/templates/book/readthrough.html:78 +#: bookwyrm/templates/book/edit_book.html:329 +#: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/moderation/report_modal.html:34 #: bookwyrm/templates/settings/federated_server.html:99 #: bookwyrm/templates/snippets/delete_readthrough_modal.html:17 #: bookwyrm/templates/snippets/goal_form.html:32 -#: bookwyrm/templates/snippets/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:37 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:28 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:43 msgid "Cancel" msgstr "取消" @@ -344,7 +341,7 @@ msgid "Add Description" msgstr "新增描述" #: bookwyrm/templates/book/book.html:137 -#: bookwyrm/templates/book/edit_book.html:136 +#: bookwyrm/templates/book/edit_book.html:143 #: bookwyrm/templates/lists/form.html:12 msgid "Description:" msgstr "描述:" @@ -427,22 +424,22 @@ msgid "ISBN:" msgstr "ISBN:" #: bookwyrm/templates/book/book_identifiers.html:14 -#: bookwyrm/templates/book/edit_book.html:301 +#: bookwyrm/templates/book/edit_book.html:308 msgid "OCLC Number:" msgstr "OCLC 號:" #: bookwyrm/templates/book/book_identifiers.html:21 -#: bookwyrm/templates/book/edit_book.html:309 +#: bookwyrm/templates/book/edit_book.html:316 msgid "ASIN:" msgstr "ASIN:" #: bookwyrm/templates/book/cover_modal.html:17 -#: bookwyrm/templates/book/edit_book.html:229 +#: bookwyrm/templates/book/edit_book.html:236 msgid "Upload cover:" msgstr "上載封面:" #: bookwyrm/templates/book/cover_modal.html:23 -#: bookwyrm/templates/book/edit_book.html:235 +#: bookwyrm/templates/book/edit_book.html:242 msgid "Load cover from url:" msgstr "從網址載入封面:" @@ -457,135 +454,135 @@ msgstr "編輯 \"%(book_title)s\"" msgid "Add Book" msgstr "新增書目" -#: bookwyrm/templates/book/edit_book.html:54 +#: bookwyrm/templates/book/edit_book.html:61 msgid "Confirm Book Info" msgstr "確認書目資料" -#: bookwyrm/templates/book/edit_book.html:62 +#: bookwyrm/templates/book/edit_book.html:69 #, python-format msgid "Is \"%(name)s\" an existing author?" msgstr "\"%(name)s\" 是已存在的作者嗎?" -#: bookwyrm/templates/book/edit_book.html:71 +#: bookwyrm/templates/book/edit_book.html:78 #, python-format msgid "Author of %(book_title)s" msgstr "%(book_title)s 的作者" -#: bookwyrm/templates/book/edit_book.html:75 +#: bookwyrm/templates/book/edit_book.html:82 msgid "This is a new author" msgstr "這是一位新的作者" -#: bookwyrm/templates/book/edit_book.html:82 +#: bookwyrm/templates/book/edit_book.html:89 #, python-format msgid "Creating a new author: %(name)s" msgstr "正在建立新的作者: %(name)s" -#: bookwyrm/templates/book/edit_book.html:89 +#: bookwyrm/templates/book/edit_book.html:96 msgid "Is this an edition of an existing work?" msgstr "這是已存在的作品的另一個版本嗎?" -#: bookwyrm/templates/book/edit_book.html:97 +#: bookwyrm/templates/book/edit_book.html:104 msgid "This is a new work" msgstr "這是一個新的作品。" -#: bookwyrm/templates/book/edit_book.html:104 +#: bookwyrm/templates/book/edit_book.html:111 #: bookwyrm/templates/password_reset.html:30 msgid "Confirm" msgstr "確認" -#: bookwyrm/templates/book/edit_book.html:106 +#: bookwyrm/templates/book/edit_book.html:113 #: bookwyrm/templates/feed/status.html:8 msgid "Back" msgstr "返回" -#: bookwyrm/templates/book/edit_book.html:120 +#: bookwyrm/templates/book/edit_book.html:127 #: bookwyrm/templates/snippets/create_status/review.html:18 msgid "Title:" msgstr "標題:" -#: bookwyrm/templates/book/edit_book.html:128 +#: bookwyrm/templates/book/edit_book.html:135 msgid "Subtitle:" msgstr "副標題:" -#: bookwyrm/templates/book/edit_book.html:144 +#: bookwyrm/templates/book/edit_book.html:151 msgid "Series:" msgstr "系列:" -#: bookwyrm/templates/book/edit_book.html:152 +#: bookwyrm/templates/book/edit_book.html:159 msgid "Series number:" msgstr "系列編號:" -#: bookwyrm/templates/book/edit_book.html:160 +#: bookwyrm/templates/book/edit_book.html:167 msgid "Languages:" msgstr "語言:" -#: bookwyrm/templates/book/edit_book.html:169 +#: bookwyrm/templates/book/edit_book.html:176 msgid "Publisher:" msgstr "出版社:" -#: bookwyrm/templates/book/edit_book.html:178 +#: bookwyrm/templates/book/edit_book.html:185 msgid "First published date:" msgstr "初版時間:" -#: bookwyrm/templates/book/edit_book.html:186 +#: bookwyrm/templates/book/edit_book.html:193 msgid "Published date:" msgstr "出版時間:" -#: bookwyrm/templates/book/edit_book.html:195 +#: bookwyrm/templates/book/edit_book.html:202 msgid "Authors" msgstr "作者" -#: bookwyrm/templates/book/edit_book.html:202 +#: bookwyrm/templates/book/edit_book.html:209 #, fuzzy, python-format #| msgid "Remove from %(name)s" msgid "Remove %(name)s" msgstr "從 %(name)s 移除" -#: bookwyrm/templates/book/edit_book.html:205 +#: bookwyrm/templates/book/edit_book.html:212 #, fuzzy, python-format #| msgid "Remove from %(name)s" msgid "Author page for %(name)s" msgstr "從 %(name)s 移除" -#: bookwyrm/templates/book/edit_book.html:212 +#: bookwyrm/templates/book/edit_book.html:219 msgid "Add Authors:" msgstr "新增作者:" -#: bookwyrm/templates/book/edit_book.html:213 +#: bookwyrm/templates/book/edit_book.html:220 msgid "John Doe, Jane Smith" msgstr "John Doe, Jane Smith" -#: bookwyrm/templates/book/edit_book.html:220 +#: bookwyrm/templates/book/edit_book.html:227 #: bookwyrm/templates/user/shelf/shelf.html:78 msgid "Cover" msgstr "封面" -#: bookwyrm/templates/book/edit_book.html:248 +#: bookwyrm/templates/book/edit_book.html:255 msgid "Physical Properties" msgstr "實體性質" -#: bookwyrm/templates/book/edit_book.html:250 +#: bookwyrm/templates/book/edit_book.html:257 #: bookwyrm/templates/book/format_filter.html:5 msgid "Format:" msgstr "格式:" -#: bookwyrm/templates/book/edit_book.html:258 +#: bookwyrm/templates/book/edit_book.html:265 msgid "Pages:" msgstr "頁數:" -#: bookwyrm/templates/book/edit_book.html:267 +#: bookwyrm/templates/book/edit_book.html:274 msgid "Book Identifiers" msgstr "書目標識號" -#: bookwyrm/templates/book/edit_book.html:269 +#: bookwyrm/templates/book/edit_book.html:276 msgid "ISBN 13:" msgstr "ISBN 13:" -#: bookwyrm/templates/book/edit_book.html:277 +#: bookwyrm/templates/book/edit_book.html:284 msgid "ISBN 10:" msgstr "ISBN 10:" -#: bookwyrm/templates/book/edit_book.html:285 +#: bookwyrm/templates/book/edit_book.html:292 msgid "Openlibrary ID:" msgstr "Openlibrary ID:" @@ -651,31 +648,37 @@ msgstr "評價了" msgid "Progress Updates:" msgstr "進度更新:" -#: bookwyrm/templates/book/readthrough.html:14 +#: bookwyrm/templates/book/readthrough.html:13 msgid "finished" msgstr "已完成" -#: bookwyrm/templates/book/readthrough.html:25 +#: bookwyrm/templates/book/readthrough.html:24 msgid "Show all updates" msgstr "顯示所有更新" -#: bookwyrm/templates/book/readthrough.html:41 +#: bookwyrm/templates/book/readthrough.html:40 msgid "Delete this progress update" msgstr "刪除此進度更新" -#: bookwyrm/templates/book/readthrough.html:52 +#: bookwyrm/templates/book/readthrough.html:51 msgid "started" msgstr "已開始" -#: bookwyrm/templates/book/readthrough.html:59 -#: bookwyrm/templates/book/readthrough.html:73 +#: bookwyrm/templates/book/readthrough.html:58 +#: bookwyrm/templates/book/readthrough.html:72 msgid "Edit read dates" msgstr "編輯閱讀日期" -#: bookwyrm/templates/book/readthrough.html:63 +#: bookwyrm/templates/book/readthrough.html:62 msgid "Delete these read dates" msgstr "刪除這些閱讀日期" +#: bookwyrm/templates/book/search_filter.html:5 +#, fuzzy +#| msgid "Search Results" +msgid "Search editions" +msgstr "搜尋結果" + #: bookwyrm/templates/components/inline_form.html:8 #: bookwyrm/templates/components/modal.html:11 #: bookwyrm/templates/feed/layout.html:71 @@ -998,18 +1001,18 @@ msgid "There are no books here right now! Try searching for a book to get starte msgstr "現在這裡還沒有任何書目!嘗試著從搜尋某本書開始吧" #: bookwyrm/templates/feed/layout.html:25 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "To Read" msgstr "想讀" #: bookwyrm/templates/feed/layout.html:26 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Currently Reading" msgstr "在讀" #: bookwyrm/templates/feed/layout.html:27 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:16 -#: bookwyrm/templates/user/shelf/shelf.html:29 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:17 +#: bookwyrm/templates/user/shelf/shelf.html:31 msgid "Read" msgstr "讀過" @@ -1024,6 +1027,12 @@ msgstr "%(year)s 閱讀目標" msgid "Who to follow" msgstr "可以關注的人" +#: bookwyrm/templates/feed/suggested_users.html:5 +#, fuzzy +#| msgid "Directory" +msgid "View directory" +msgstr "目錄" + #: bookwyrm/templates/get_started/book_preview.html:6 #, python-format msgid "Have you read %(book_title)s?" @@ -1039,7 +1048,6 @@ msgid "Search for a book" msgstr "搜尋書目" #: bookwyrm/templates/get_started/books.html:11 -#: bookwyrm/templates/isbn_search_results.html:17 #, python-format msgid "No books found for \"%(query)s\"" msgstr "沒有找到 \"%(query)s\" 的書目" @@ -1187,7 +1195,7 @@ msgid "%(username)s's %(year)s Books" msgstr "%(username)s 在 %(year)s 的書目" #: bookwyrm/templates/import.html:5 bookwyrm/templates/import.html:9 -#: bookwyrm/templates/user/shelf/shelf.html:40 +#: bookwyrm/templates/user/shelf/shelf.html:42 msgid "Import Books" msgstr "匯入書目" @@ -1239,7 +1247,7 @@ msgstr "匯入開始:" msgid "Import completed:" msgstr "匯入完成:" -#: bookwyrm/templates/import_status.html:25 +#: bookwyrm/templates/import_status.html:24 msgid "TASK FAILED" msgstr "任務失敗" @@ -1316,19 +1324,6 @@ msgstr "沒有權限" msgid "Sorry! This invite code is no longer valid." msgstr "抱歉!此邀請碼已不再有效。" -#: bookwyrm/templates/isbn_search_results.html:4 -msgid "Search Results" -msgstr "搜尋結果" - -#: bookwyrm/templates/isbn_search_results.html:9 -#, python-format -msgid "Search Results for \"%(query)s\"" -msgstr "\"%(query)s\" 的搜尋結果" - -#: bookwyrm/templates/isbn_search_results.html:14 -msgid "Matching Books" -msgstr "匹配的書目" - #: bookwyrm/templates/landing/about.html:7 #, python-format msgid "About %(site_name)s" @@ -1468,6 +1463,10 @@ msgstr "在 %(support_title)s msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub." msgstr "BookWyrm 是開源軟體。你可以在 GitHub 貢獻或報告問題。" +#: bookwyrm/templates/lists/bookmark_button.html:30 +msgid "Un-save" +msgstr "" + #: bookwyrm/templates/lists/create_form.html:5 #: bookwyrm/templates/lists/lists.html:20 msgid "Create List" @@ -1607,10 +1606,28 @@ msgstr "沒有符合 \"%(query)s\" 請求的書目" msgid "Suggest" msgstr "推薦" +#: bookwyrm/templates/lists/list_items.html:15 +#, fuzzy +#| msgid "Save" +msgid "Saved" +msgstr "儲存" + #: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:9 msgid "Your Lists" msgstr "你的列表" +#: bookwyrm/templates/lists/lists.html:35 +#, fuzzy +#| msgid "Lists" +msgid "All Lists" +msgstr "列表" + +#: bookwyrm/templates/lists/lists.html:39 +#, fuzzy +#| msgid "Create List" +msgid "Saved Lists" +msgstr "建立列表" + #: bookwyrm/templates/login.html:4 msgid "Login" msgstr "登入" @@ -2082,23 +2099,23 @@ msgstr "活躍:" msgid "Create Announcement" msgstr "建立公告" -#: bookwyrm/templates/settings/announcements.html:22 +#: bookwyrm/templates/settings/announcements.html:21 msgid "Date added" msgstr "新增日期:" -#: bookwyrm/templates/settings/announcements.html:26 +#: bookwyrm/templates/settings/announcements.html:25 msgid "Preview" msgstr "預覽" -#: bookwyrm/templates/settings/announcements.html:30 +#: bookwyrm/templates/settings/announcements.html:29 msgid "Start date" msgstr "開始日期" -#: bookwyrm/templates/settings/announcements.html:34 +#: bookwyrm/templates/settings/announcements.html:33 msgid "End date" msgstr "結束日期" -#: bookwyrm/templates/settings/announcements.html:38 +#: bookwyrm/templates/settings/announcements.html:37 #: bookwyrm/templates/settings/federation.html:30 #: bookwyrm/templates/settings/manage_invite_requests.html:44 #: bookwyrm/templates/settings/status_filter.html:5 @@ -2106,11 +2123,11 @@ msgstr "結束日期" msgid "Status" msgstr "狀態" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "active" msgstr "啟用" -#: bookwyrm/templates/settings/announcements.html:48 +#: bookwyrm/templates/settings/announcements.html:47 msgid "inactive" msgstr "停用" @@ -2454,7 +2471,7 @@ msgid "and %(remainder_count_display)s other" msgid_plural "and %(remainder_count_display)s others" msgstr[0] "" -#: bookwyrm/templates/snippets/book_cover.html:32 +#: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" msgstr "沒有封面" @@ -2487,24 +2504,24 @@ msgid "Some thoughts on the book" msgstr "" #: bookwyrm/templates/snippets/create_status/comment.html:26 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:16 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:16 msgid "Progress:" msgstr "進度:" #: bookwyrm/templates/snippets/create_status/comment.html:34 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:30 #: bookwyrm/templates/snippets/readthrough_form.html:22 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:30 msgid "pages" msgstr "頁數" #: bookwyrm/templates/snippets/create_status/comment.html:35 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:31 #: bookwyrm/templates/snippets/readthrough_form.html:23 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:31 msgid "percent" msgstr "百分比" #: bookwyrm/templates/snippets/create_status/comment.html:41 -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:36 +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:36 #, python-format msgid "of %(pages)s pages" msgstr "全書 %(pages)s 頁" @@ -2533,6 +2550,7 @@ msgid "Include spoiler alert" msgstr "加入劇透警告" #: bookwyrm/templates/snippets/create_status/layout.html:38 +#: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" msgstr "評論:" @@ -2576,13 +2594,13 @@ msgstr "刪除這些閱讀日期嗎?" msgid "You are deleting this readthrough and its %(count)s associated progress updates." msgstr "你正要刪除這篇閱讀經過以及與之相關的 %(count)s 次進度更新。" -#: bookwyrm/templates/snippets/fav_button.html:10 -#: bookwyrm/templates/snippets/fav_button.html:12 +#: bookwyrm/templates/snippets/fav_button.html:16 +#: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" msgstr "喜歡" -#: bookwyrm/templates/snippets/fav_button.html:18 -#: bookwyrm/templates/snippets/fav_button.html:19 +#: bookwyrm/templates/snippets/fav_button.html:30 +#: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" msgstr "取消喜歡" @@ -2685,9 +2703,7 @@ msgid "Goal privacy:" msgstr "目標隱私:" #: bookwyrm/templates/snippets/goal_form.html:26 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:37 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:31 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:20 +#: bookwyrm/templates/snippets/reading_modals/layout.html:13 msgid "Post to feed" msgstr "發佈到即時動態" @@ -2762,21 +2778,45 @@ msgstr "留下評價" msgid "Rate" msgstr "評價" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6 +#, python-format +msgid "Finish \"%(book_title)s\"" +msgstr "完成 \"%(book_title)s\"" + +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:22 +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:20 #: bookwyrm/templates/snippets/readthrough_form.html:7 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:19 -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:19 msgid "Started reading" msgstr "已開始閱讀" +#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:30 +#: bookwyrm/templates/snippets/readthrough_form.html:30 +msgid "Finished reading" +msgstr "已完成閱讀" + +#: bookwyrm/templates/snippets/reading_modals/form.html:8 +msgid "(Optional)" +msgstr "" + +#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:5 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:47 +msgid "Update progress" +msgstr "更新進度" + +#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6 +#, python-format +msgid "Start \"%(book_title)s\"" +msgstr "開始 \"%(book_title)s\"" + +#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6 +#, python-format +msgid "Want to Read \"%(book_title)s\"" +msgstr "想要閱讀 \"%(book_title)s\"" + #: bookwyrm/templates/snippets/readthrough_form.html:14 msgid "Progress" msgstr "進度" -#: bookwyrm/templates/snippets/readthrough_form.html:30 -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:25 -msgid "Finished reading" -msgstr "已完成閱讀" - #: bookwyrm/templates/snippets/register_form.html:32 msgid "Sign Up" msgstr "註冊" @@ -2793,16 +2833,6 @@ msgstr "匯入書目" msgid "Move book" msgstr "移動書目" -#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:5 -#, python-format -msgid "Finish \"%(book_title)s\"" -msgstr "完成 \"%(book_title)s\"" - -#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:5 -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:45 -msgid "Update progress" -msgstr "更新進度" - #: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5 msgid "More shelves" msgstr "更多書架" @@ -2811,30 +2841,19 @@ msgstr "更多書架" msgid "Start reading" msgstr "開始閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:19 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21 msgid "Finish reading" msgstr "完成閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:25 -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:26 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:27 msgid "Want to read" msgstr "想要閱讀" -#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:57 +#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:59 #, python-format msgid "Remove from %(name)s" msgstr "從 %(name)s 移除" -#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:5 -#, python-format -msgid "Start \"%(book_title)s\"" -msgstr "開始 \"%(book_title)s\"" - -#: bookwyrm/templates/snippets/shelve_button/want_to_read_modal.html:5 -#, python-format -msgid "Want to Read \"%(book_title)s\"" -msgstr "想要閱讀 \"%(book_title)s\"" - #: bookwyrm/templates/snippets/status/content_status.html:72 #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" @@ -2872,13 +2891,13 @@ msgstr "移除 %(name)s" msgid "rated %(book)s:" msgstr "由 %(username)s 建立" -#: bookwyrm/templates/snippets/status/headers/read.html:5 +#: bookwyrm/templates/snippets/status/headers/read.html:7 #, fuzzy, python-format #| msgid "Editions of \"%(work_title)s\"" msgid "finished reading %(book)s" msgstr "\"%(work_title)s\" 的各版本" -#: bookwyrm/templates/snippets/status/headers/reading.html:6 +#: bookwyrm/templates/snippets/status/headers/reading.html:7 #, fuzzy, python-format #| msgid "Created by %(username)s" msgid "started reading %(book)s" @@ -2890,7 +2909,7 @@ msgstr "由 %(username)s 建立" msgid "reviewed %(book)s" msgstr "移除 %(name)s" -#: bookwyrm/templates/snippets/status/headers/to_read.html:6 +#: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, fuzzy, python-format #| msgid "replied to %(username)s's status" msgid "%(username)s wants to read %(book)s" @@ -3015,11 +3034,11 @@ msgstr "編輯書架" msgid "Update shelf" msgstr "更新書架" -#: bookwyrm/templates/user/shelf/shelf.html:25 bookwyrm/views/shelf.py:56 +#: bookwyrm/templates/user/shelf/shelf.html:27 bookwyrm/views/shelf.py:56 msgid "All books" msgstr "所有書目" -#: bookwyrm/templates/user/shelf/shelf.html:38 +#: bookwyrm/templates/user/shelf/shelf.html:40 msgid "Create shelf" msgstr "建立書架" @@ -3175,11 +3194,11 @@ msgstr "取消停用使用者" msgid "Access level:" msgstr "訪問權限:" -#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:22 +#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" msgstr "檔案超過了最大大小: 10MB" -#: bookwyrm/templatetags/utilities.py:30 +#: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "" @@ -3201,6 +3220,17 @@ msgstr "沒有找到使用該郵箱的使用者。" msgid "A password reset link sent to %s" msgstr "密碼重置連結已傳送給 %s" +#: bookwyrm/views/rss_feed.py:34 +#, python-brace-format +msgid "Status updates from {obj.display_name}" +msgstr "" + +#~ msgid "Search Results for \"%(query)s\"" +#~ msgstr "\"%(query)s\" 的搜尋結果" + +#~ msgid "Matching Books" +#~ msgstr "匹配的書目" + #~ msgid "Local Timeline" #~ msgstr "本地時間線" diff --git a/requirements.txt b/requirements.txt index ec0eb1a81..37be89440 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,12 @@ celery==4.4.2 colorthief==0.2.1 Django==3.2.4 +django-imagekit==4.0.2 django-model-utils==4.0.0 environs==7.2.0 flower==0.9.4 Markdown==3.3.3 -Pillow>=7.1.0 +Pillow>=8.2.0 psycopg2==2.8.4 pycryptodome==3.9.4 python-dateutil==2.8.1