+ {% include 'snippets/move_user_buttons.html' with group=notification.related_group %}
+
+ {% else %}
+ {% blocktrans trimmed %}
+ {{ related_user }} has undone their move
+ {% endblocktrans %}
+ {% endif %}
+{% endblock %}
diff --git a/bookwyrm/templates/preferences/alias_user.html b/bookwyrm/templates/preferences/alias_user.html
new file mode 100644
index 000000000..e1e468208
--- /dev/null
+++ b/bookwyrm/templates/preferences/alias_user.html
@@ -0,0 +1,59 @@
+{% extends 'preferences/layout.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Move Account" %}{% endblock %}
+
+{% block header %}
+{% trans "Create Alias" %}
+{% endblock %}
+
+{% block panel %}
+
{% url 'prefs-delete' as url %}
{% trans "Delete Account" %}
diff --git a/bookwyrm/templates/preferences/move_user.html b/bookwyrm/templates/preferences/move_user.html
new file mode 100644
index 000000000..47b370e82
--- /dev/null
+++ b/bookwyrm/templates/preferences/move_user.html
@@ -0,0 +1,43 @@
+{% extends 'preferences/layout.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Move Account" %}{% endblock %}
+
+{% block header %}
+{% trans "Move Account" %}
+{% endblock %}
+
+{% block panel %}
+
+
{% trans "Migrate account to another server" %}
+
+
+
+ {% trans "Moving your account will notify all your followers and direct them to follow the new account." %}
+
+
+ {% blocktrans %}
+ {{ user }} will be marked as moved and will not be discoverable or usable unless you undo the move.
+ {% endblocktrans %}
+
+
+
+
{% trans "Remember to add this user as an alias of the target account before you try to move." %}
+
+
+
+
+{% endblock %}
diff --git a/bookwyrm/templates/settings/celery.html b/bookwyrm/templates/settings/celery.html
index 2f4a36ce9..b224e20cc 100644
--- a/bookwyrm/templates/settings/celery.html
+++ b/bookwyrm/templates/settings/celery.html
@@ -29,7 +29,7 @@
-
+
{{ queues.broadcast|intcomma }}
diff --git a/bookwyrm/templates/settings/users/user_admin.html b/bookwyrm/templates/settings/users/user_admin.html
index 9bc5805b1..cc5c51ba7 100644
--- a/bookwyrm/templates/settings/users/user_admin.html
+++ b/bookwyrm/templates/settings/users/user_admin.html
@@ -74,24 +74,7 @@
{{ user.created_date }}
{{ user.last_active_date }}
- {% if user.is_active %}
-
-
-
- {% trans "Active" %}
- {% elif user.deactivation_reason == "moderator_deletion" or user.deactivation_reason == "self_deletion" %}
-
-
-
- {% trans "Deleted" %}
- ({{ user.get_deactivation_reason_display }})
- {% else %}
-
-
-
- {% trans "Inactive" %}
- ({{ user.get_deactivation_reason_display }})
- {% endif %}
+ {% include "snippets/user_active_tag.html" with user=user %}
{% if status == "federated" %}
diff --git a/bookwyrm/templates/settings/users/user_info.html b/bookwyrm/templates/settings/users/user_info.html
index a1725ae36..f35c60db9 100644
--- a/bookwyrm/templates/settings/users/user_info.html
+++ b/bookwyrm/templates/settings/users/user_info.html
@@ -23,18 +23,7 @@
{% trans "Status" %}
- {% if user.is_active %}
-
- {% trans "Active" %}
-
- {% else %}
-
- {% trans "Inactive" %}
- {% if user.deactivation_reason %}
- ({% trans user.get_deactivation_reason_display %})
- {% endif %}
-
- {% endif %}
+ {% include "snippets/user_active_tag.html" with large=True %}
{% if user.local %}
{% trans "Local" %}
diff --git a/bookwyrm/templates/shelf/shelf.html b/bookwyrm/templates/shelf/shelf.html
index 7d0035ed3..a2410ef95 100644
--- a/bookwyrm/templates/shelf/shelf.html
+++ b/bookwyrm/templates/shelf/shelf.html
@@ -18,7 +18,22 @@
{% include 'user/books_header.html' %}
-
+{% if user.moved_to %}
+
+
+
+ {% trans "You have have moved to" %}
+ {% id_to_username user.moved_to %}
+
+
{% trans "You can undo this move to restore full functionality, but some followers may have already unfollowed this account." %}
+
+
+
+{% else %}
{% trans "User profile" %}
@@ -215,6 +230,7 @@
{% include 'snippets/pagination.html' with page=books path=request.path %}
+{% endif %}
{% endblock %}
{% block scripts %}
diff --git a/bookwyrm/templates/snippets/move_user_buttons.html b/bookwyrm/templates/snippets/move_user_buttons.html
new file mode 100644
index 000000000..fc8f792e9
--- /dev/null
+++ b/bookwyrm/templates/snippets/move_user_buttons.html
@@ -0,0 +1,13 @@
+{% load i18n %}
+{% load utilities %}
+
+
+{% if related_user_moved_to|user_from_remote_id not in request.user.following.all %}
+
+
+
+{% endif %}
\ No newline at end of file
diff --git a/bookwyrm/templates/snippets/user_active_tag.html b/bookwyrm/templates/snippets/user_active_tag.html
new file mode 100644
index 000000000..1d85ae68b
--- /dev/null
+++ b/bookwyrm/templates/snippets/user_active_tag.html
@@ -0,0 +1,17 @@
+{% load i18n %}
+
+{% if user.is_active %}
+ {% if user.moved_to %}
+ {% trans "Moved" as text %}
+ {% include "snippets/user_active_tag_item.html" with icon="x" text=text level="info" %}
+ {% else %}
+ {% trans "Active" as text %}
+ {% include "snippets/user_active_tag_item.html" with icon="check" text=text level="success" %}
+ {% endif %}
+{% elif user.is_deleted %}
+ {% trans "Deleted" as text %}
+ {% include "snippets/user_active_tag_item.html" with icon="x" text=text level="danger" deactivation_reason=user.get_deactivation_reason_display %}
+{% else %}
+ {% trans "Inactive" as text %}
+ {% include "snippets/user_active_tag_item.html" with icon="x" text=text level="warning" deactivation_reason=user.get_deactivation_reason_display %}
+{% endif %}
diff --git a/bookwyrm/templates/snippets/user_active_tag_item.html b/bookwyrm/templates/snippets/user_active_tag_item.html
new file mode 100644
index 000000000..e722150f2
--- /dev/null
+++ b/bookwyrm/templates/snippets/user_active_tag_item.html
@@ -0,0 +1,19 @@
+{% if large %}
+
+
+
+ {{ text }}
+ {% if deactivation_reason %}
+ ({{ deactivation_reason }})
+ {% endif %}
+
+
+{% else %}
+
+
+
+
+{{ text }}
+
+{% endif %}
+
diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html
index 4c7031ba5..57d25120d 100755
--- a/bookwyrm/templates/user/layout.html
+++ b/bookwyrm/templates/user/layout.html
@@ -5,6 +5,7 @@
{% load markdown %}
{% load layout %}
{% load group_tags %}
+{% load user_page_tags %}
{% block title %}{{ user.display_name }}{% endblock %}
@@ -27,7 +28,11 @@
- {% include 'user/user_preview.html' with user=user %}
+ {% if user.moved_to %}
+ {% include 'user/moved.html' with user=user %}
+ {% else %}
+ {% include 'user/user_preview.html' with user=user %}
+ {% endif %}
{% if user.summary %}
@@ -38,70 +43,83 @@
{% endspaceless %}
{% endif %}
- {% if not is_self and request.user.is_authenticated %}
- {% include 'snippets/follow_button.html' with user=user %}
- {% endif %}
- {% if not is_self %}
- {% include 'ostatus/remote_follow_button.html' with user=user %}
- {% endif %}
-
- {% if is_self and user.active_follower_requests.all %}
-
-
{% trans "Follow Requests" %}
- {% for requester in user.follower_requests.all %}
-
-
- {{ requester.display_name }} ({{ requester.username }})
-
- {% include 'snippets/follow_request_buttons.html' with user=requester %}
+
+ {% if user.moved_to %}
+
+
+
+ {% else %}
+ {% if not is_self and request.user.is_authenticated %}
+ {% include 'snippets/follow_button.html' with user=user %}
+ {% endif %}
+ {% if not is_self %}
+ {% include 'ostatus/remote_follow_button.html' with user=user %}
+ {% endif %}
+
+ {% if is_self and user.active_follower_requests.all %}
+
+
{% trans "Follow Requests" %}
+ {% for requester in user.follower_requests.all %}
+
+ {% endfor %}
+
+ {% endif %}
{% endif %}
+
+ {% block tabs %}
+ {% if not user.moved_to %}
+ {% with user|username as username %}
+
+
+ {% url 'user-feed' user|username as url %}
+
+ {% trans "Activity" %}
+
+ {% url 'user-reviews-comments' user|username as url %}
+
+ {% trans "Reviews and Comments" %}
+
+ {% if is_self or user.goal.exists %}
+ {% now 'Y' as year %}
+ {% url 'user-goal' user|username year as url %}
+
+ {% trans "Reading Goal" %}
+
+ {% endif %}
+ {% if is_self or user|has_groups %}
+ {% url 'user-groups' user|username as url %}
+
+ {% trans "Groups" %}
+
+ {% endif %}
+ {% if is_self or user.list_set.exists %}
+ {% url 'user-lists' user|username as url %}
+
+ {% trans "Lists" %}
+
+ {% endif %}
+ {% if user.shelf_set.exists %}
+ {% url 'user-shelves' user|username as url %}
+
+ {% trans "Books" %}
+
+ {% endif %}
+
+
+ {% endwith %}
+ {% endif %}
+ {% endblock %}
-{% block tabs %}
-{% with user|username as username %}
-
-
- {% url 'user-feed' user|username as url %}
-
- {% trans "Activity" %}
-
- {% url 'user-reviews-comments' user|username as url %}
-
- {% trans "Reviews and Comments" %}
-
- {% if is_self or user.goal.exists %}
- {% now 'Y' as year %}
- {% url 'user-goal' user|username year as url %}
-
- {% trans "Reading Goal" %}
-
- {% endif %}
- {% if is_self or user|has_groups %}
- {% url 'user-groups' user|username as url %}
-
- {% trans "Groups" %}
-
- {% endif %}
- {% if is_self or user.list_set.exists %}
- {% url 'user-lists' user|username as url %}
-
- {% trans "Lists" %}
-
- {% endif %}
- {% if user.shelf_set.exists %}
- {% url 'user-shelves' user|username as url %}
-
- {% trans "Books" %}
-
- {% endif %}
-
-
-{% endwith %}
-{% endblock %}
-
-{% block panel %}{% endblock %}
-
+ {% if not user.moved_to %}
+ {% block panel %}{% endblock %}
+ {% endif %}
{% endblock %}
diff --git a/bookwyrm/templates/user/moved.html b/bookwyrm/templates/user/moved.html
new file mode 100644
index 000000000..45a4bb2e5
--- /dev/null
+++ b/bookwyrm/templates/user/moved.html
@@ -0,0 +1,27 @@
+{% load i18n %}
+{% load humanize %}
+{% load utilities %}
+{% load markdown %}
+{% load layout %}
+{% load group_tags %}
+
+
+
diff --git a/bookwyrm/templates/user_menu.html b/bookwyrm/templates/user_menu.html
index 5473b9da2..ad6f4fab2 100644
--- a/bookwyrm/templates/user_menu.html
+++ b/bookwyrm/templates/user_menu.html
@@ -34,11 +34,6 @@
{% trans "Directory" %}
-
-
- {% trans 'Your Books' %}
-
-
{% trans "Direct Messages" %}
diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py
index 4aaf6b8a7..42e67990f 100644
--- a/bookwyrm/templatetags/utilities.py
+++ b/bookwyrm/templatetags/utilities.py
@@ -2,11 +2,13 @@
import os
import re
from uuid import uuid4
+from urllib.parse import urlparse
from django import template
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.templatetags.static import static
+from bookwyrm.models import User
register = template.Library()
@@ -29,6 +31,13 @@ def get_user_identifier(user):
return user.localname if user.localname else user.username
+@register.filter(name="user_from_remote_id")
+def get_user_identifier_from_remote_id(remote_id):
+ """get the local user id from their remote id"""
+ user = User.objects.get(remote_id=remote_id)
+ return user if user else None
+
+
@register.filter(name="book_title")
def get_title(book, too_short=5):
"""display the subtitle if the title is short"""
@@ -103,3 +112,16 @@ def get_isni(existing, author, autoescape=True):
f' '
)
return ""
+
+
+@register.simple_tag(takes_context=False)
+def id_to_username(user_id):
+ """given an arbitrary remote id, return the username"""
+ if user_id:
+ url = urlparse(user_id)
+ domain = url.netloc
+ parts = url.path.split("/")
+ name = parts[-1]
+ value = f"{name}@{domain}"
+
+ return value
diff --git a/bookwyrm/tests/migrations/test_0184.py b/bookwyrm/tests/migrations/test_0184.py
new file mode 100644
index 000000000..4bf1b66c9
--- /dev/null
+++ b/bookwyrm/tests/migrations/test_0184.py
@@ -0,0 +1,121 @@
+""" testing migrations """
+from unittest.mock import patch
+
+from django.test import TestCase
+from django.db.migrations.executor import MigrationExecutor
+from django.db import connection
+
+from bookwyrm import models
+from bookwyrm.management.commands import initdb
+from bookwyrm.settings import DOMAIN
+
+# pylint: disable=missing-class-docstring
+# pylint: disable=missing-function-docstring
+class EraseDeletedUserDataMigration(TestCase):
+
+ migrate_from = "0183_auto_20231105_1607"
+ migrate_to = "0184_auto_20231106_0421"
+
+ # pylint: disable=invalid-name
+ def setUp(self):
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.active_user = models.User.objects.create_user(
+ f"activeuser@{DOMAIN}",
+ "activeuser@activeuser.activeuser",
+ "activeuserword",
+ local=True,
+ localname="active",
+ name="a name",
+ )
+ self.inactive_user = models.User.objects.create_user(
+ f"inactiveuser@{DOMAIN}",
+ "inactiveuser@inactiveuser.inactiveuser",
+ "inactiveuserword",
+ local=True,
+ localname="inactive",
+ is_active=False,
+ deactivation_reason="self_deactivation",
+ name="name name",
+ )
+ self.deleted_user = models.User.objects.create_user(
+ f"deleteduser@{DOMAIN}",
+ "deleteduser@deleteduser.deleteduser",
+ "deleteduserword",
+ local=True,
+ localname="deleted",
+ is_active=False,
+ deactivation_reason="self_deletion",
+ name="cool name",
+ )
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ), patch("bookwyrm.activitystreams.add_status_task.delay"):
+ self.active_status = models.Status.objects.create(
+ user=self.active_user, content="don't delete me"
+ )
+ self.inactive_status = models.Status.objects.create(
+ user=self.inactive_user, content="also don't delete me"
+ )
+ self.deleted_status = models.Status.objects.create(
+ user=self.deleted_user, content="yes, delete me"
+ )
+
+ initdb.init_groups()
+ initdb.init_permissions()
+
+ self.migrate_from = [("bookwyrm", self.migrate_from)]
+ self.migrate_to = [("bookwyrm", self.migrate_to)]
+ executor = MigrationExecutor(connection)
+ old_apps = executor.loader.project_state(self.migrate_from).apps
+
+ # Reverse to the original migration
+ executor.migrate(self.migrate_from)
+
+ self.setUpBeforeMigration(old_apps)
+
+ # Run the migration to test
+ executor = MigrationExecutor(connection)
+ executor.loader.build_graph() # reload.
+ with patch("bookwyrm.activitystreams.remove_status_task.delay"):
+ executor.migrate(self.migrate_to)
+
+ self.apps = executor.loader.project_state(self.migrate_to).apps
+
+ def setUpBeforeMigration(self, apps):
+ pass
+
+ def test_user_data_deleted(self):
+ """Make sure that only the right data was deleted"""
+ self.active_user.refresh_from_db()
+ self.inactive_user.refresh_from_db()
+ self.deleted_user.refresh_from_db()
+ self.active_status.refresh_from_db()
+ self.inactive_status.refresh_from_db()
+ self.deleted_status.refresh_from_db()
+
+ self.assertTrue(self.active_user.is_active)
+ self.assertFalse(self.active_user.is_deleted)
+ self.assertEqual(self.active_user.name, "a name")
+ self.assertNotEqual(self.deleted_user.email, "activeuser@activeuser.activeuser")
+ self.assertFalse(self.active_status.deleted)
+ self.assertEqual(self.active_status.content, "don't delete me")
+
+ self.assertFalse(self.inactive_user.is_active)
+ self.assertFalse(self.inactive_user.is_deleted)
+ self.assertEqual(self.inactive_user.name, "name name")
+ self.assertNotEqual(
+ self.deleted_user.email, "inactiveuser@inactiveuser.inactiveuser"
+ )
+ self.assertFalse(self.inactive_status.deleted)
+ self.assertEqual(self.inactive_status.content, "also don't delete me")
+
+ self.assertFalse(self.deleted_user.is_active)
+ self.assertTrue(self.deleted_user.is_deleted)
+ self.assertIsNone(self.deleted_user.name)
+ self.assertNotEqual(
+ self.deleted_user.email, "deleteduser@deleteduser.deleteduser"
+ )
+ self.assertTrue(self.deleted_status.deleted)
+ self.assertIsNone(self.deleted_status.content)
diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py
index a465c2c12..645a6546b 100644
--- a/bookwyrm/tests/models/test_activitypub_mixin.py
+++ b/bookwyrm/tests/models/test_activitypub_mixin.py
@@ -119,6 +119,25 @@ class ActivitypubMixins(TestCase):
result = models.Edition.find_existing({"openlibraryKey": "OL1234"})
self.assertEqual(result, book)
+ def test_find_existing_with_id(self, *_):
+ """make sure that an "id" field won't produce a match"""
+ book = models.Edition.objects.create(title="Test edition")
+
+ result = models.Edition.find_existing({"id": book.id})
+ self.assertIsNone(result)
+
+ def test_find_existing_with_id_and_match(self, *_):
+ """make sure that an "id" field won't produce a match"""
+ book = models.Edition.objects.create(title="Test edition")
+ matching_book = models.Edition.objects.create(
+ title="Another test edition", openlibrary_key="OL1234"
+ )
+
+ result = models.Edition.find_existing(
+ {"id": book.id, "openlibraryKey": "OL1234"}
+ )
+ self.assertEqual(result, matching_book)
+
def test_get_recipients_public_object(self, *_):
"""determines the recipients for an object's broadcast"""
MockSelf = namedtuple("Self", ("privacy"))
diff --git a/bookwyrm/tests/models/test_book_model.py b/bookwyrm/tests/models/test_book_model.py
index 8122e9505..4347efcb6 100644
--- a/bookwyrm/tests/models/test_book_model.py
+++ b/bookwyrm/tests/models/test_book_model.py
@@ -11,7 +11,7 @@ from django.test import TestCase
from django.utils import timezone
from bookwyrm import models, settings
-from bookwyrm.models.book import isbn_10_to_13, isbn_13_to_10
+from bookwyrm.models.book import isbn_10_to_13, isbn_13_to_10, normalize_isbn
from bookwyrm.settings import ENABLE_THUMBNAIL_GENERATION
@@ -72,6 +72,10 @@ class Book(TestCase):
isbn_10 = isbn_13_to_10(isbn_13)
self.assertEqual(isbn_10, "178816167X")
+ def test_normalize_isbn(self):
+ """Remove misc characters from ISBNs"""
+ self.assertEqual(normalize_isbn("978-0-4633461-1-2"), "9780463346112")
+
def test_get_edition_info(self):
"""text slug about an edition"""
book = models.Edition.objects.create(title="Test Edition")
diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py
index 9d6294768..30d7918c0 100644
--- a/bookwyrm/tests/models/test_user_model.py
+++ b/bookwyrm/tests/models/test_user_model.py
@@ -1,7 +1,9 @@
""" testing models """
import json
+
from unittest.mock import patch
from django.contrib.auth.models import Group
+from django.db import IntegrityError
from django.test import TestCase
import responses
@@ -9,9 +11,11 @@ from bookwyrm import models
from bookwyrm.management.commands import initdb
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://"
# pylint: disable=invalid-name
@@ -26,6 +30,7 @@ class User(TestCase):
local=True,
localname="mouse",
name="hi",
+ summary="a summary",
bookwyrm_user=False,
)
self.another_user = models.User.objects.create_user(
@@ -88,9 +93,11 @@ class User(TestCase):
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
+ "alsoKnownAs": {"@id": "as:alsoKnownAs", "@type": "@id"},
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "movedTo": {"@id": "as:movedTo", "@type": "@id"},
+ "schema": "http://schema.org#",
"value": "schema:value",
},
],
@@ -216,19 +223,71 @@ class User(TestCase):
@patch("bookwyrm.suggested_users.remove_user_task.delay")
def test_delete_user(self, _):
- """deactivate a user"""
+ """permanently delete a user"""
self.assertTrue(self.user.is_active)
+ self.assertEqual(self.user.name, "hi")
+ self.assertEqual(self.user.summary, "a summary")
+ self.assertEqual(self.user.email, "mouse@mouse.mouse")
with patch(
"bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
- ) as broadcast_mock:
+ ) as broadcast_mock, patch(
+ "bookwyrm.models.user.User.erase_user_statuses"
+ ) as erase_statuses_mock:
self.user.delete()
+ self.assertEqual(erase_statuses_mock.call_count, 1)
+
+ # make sure the deletion is broadcast
self.assertEqual(broadcast_mock.call_count, 1)
activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"], self.user.remote_id)
+
+ self.user.refresh_from_db()
+
+ # the user's account data should be deleted
+ self.assertIsNone(self.user.name)
+ self.assertIsNone(self.user.summary)
+ self.assertNotEqual(self.user.email, "mouse@mouse.mouse")
self.assertFalse(self.user.is_active)
+ @patch("bookwyrm.suggested_users.remove_user_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+ @patch("bookwyrm.activitystreams.add_status_task.delay")
+ @patch("bookwyrm.activitystreams.remove_status_task.delay")
+ def test_delete_user_erase_statuses(self, *_):
+ """erase user statuses when user is deleted"""
+ status = models.Status.objects.create(user=self.user, content="hello")
+ self.assertFalse(status.deleted)
+ self.assertIsNotNone(status.content)
+ self.assertIsNone(status.deleted_date)
+
+ self.user.delete()
+ status.refresh_from_db()
+
+ self.assertTrue(status.deleted)
+ self.assertIsNone(status.content)
+ self.assertIsNotNone(status.deleted_date)
+
+ @patch("bookwyrm.suggested_users.remove_user_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+ @patch("bookwyrm.activitystreams.add_status_task.delay")
+ def test_delete_user_erase_statuses_invalid(self, *_):
+ """erase user statuses when user is deleted"""
+ status = models.Status.objects.create(user=self.user, content="hello")
+ self.assertFalse(status.deleted)
+ self.assertIsNotNone(status.content)
+ self.assertIsNone(status.deleted_date)
+
+ self.user.deactivate()
+ with self.assertRaises(IntegrityError):
+ self.user.erase_user_statuses()
+
+ status.refresh_from_db()
+ self.assertFalse(status.deleted)
+ self.assertIsNotNone(status.content)
+ self.assertIsNone(status.deleted_date)
+
def test_admins_no_admins(self):
"""list of admins"""
result = models.User.admins()
diff --git a/bookwyrm/tests/test_isbn.py b/bookwyrm/tests/test_isbn.py
index b528e9210..5486c7151 100644
--- a/bookwyrm/tests/test_isbn.py
+++ b/bookwyrm/tests/test_isbn.py
@@ -29,3 +29,10 @@ class TestISBN(TestCase):
self.assertEqual(hyphenator.hyphenate("9786769533251"), "9786769533251")
# 979-8 (United States) 2300000-3499999 (unassigned)
self.assertEqual(hyphenator.hyphenate("9798311111111"), "9798311111111")
+
+ def test_isbn_hyphenation_invalid_data(self):
+ """Make sure not to throw an error when a bad ISBN is found"""
+ # no action taken
+ self.assertEqual(hyphenator.hyphenate("978-0-4633461-1-2"), "978-0-4633461-1-2")
+ self.assertEqual(hyphenator.hyphenate("9-0-4633461-1-2"), "9-0-4633461-1-2")
+ self.assertEqual(hyphenator.hyphenate("90463346112"), "90463346112")
diff --git a/bookwyrm/tests/views/inbox/test_inbox_delete.py b/bookwyrm/tests/views/inbox/test_inbox_delete.py
index 0fb108e22..7b4c12564 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_delete.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_delete.py
@@ -11,6 +11,7 @@ from bookwyrm import models, views
class InboxActivities(TestCase):
"""inbox tests"""
+ # pylint: disable=invalid-name
def setUp(self):
"""basic user and book data"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
@@ -97,7 +98,8 @@ class InboxActivities(TestCase):
self.assertEqual(models.Notification.objects.get(), notif)
@patch("bookwyrm.suggested_users.remove_user_task.delay")
- def test_delete_user(self, _):
+ @patch("bookwyrm.activitystreams.remove_status_task.delay")
+ def test_delete_user(self, *_):
"""delete a user"""
self.assertTrue(models.User.objects.get(username="rat@example.com").is_active)
activity = {
diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py
index 33bd8b53a..424698130 100644
--- a/bookwyrm/tests/views/test_status.py
+++ b/bookwyrm/tests/views/test_status.py
@@ -420,21 +420,25 @@ http://www.fish.com/"""
'okay\n\n www.fish.com/ ',
)
- def test_format_links_parens(self, *_):
- """find and format urls into a tags"""
- url = "http://www.fish.com/"
- self.assertEqual(
- views.status.format_links(f"({url})"),
- f'(www.fish.com/ )',
- )
-
def test_format_links_punctuation(self, *_):
- """don’t take trailing punctuation into account pls"""
- url = "http://www.fish.com/"
- self.assertEqual(
- views.status.format_links(f"{url}."),
- f'www.fish.com/ .',
- )
+ """test many combinations of brackets, URLs, and punctuation"""
+ url = "https://bookwyrm.social"
+ html = f'bookwyrm.social '
+ test_table = [
+ ("punct", f"text and {url}.", f"text and {html}."),
+ ("multi_punct", f"text, then {url}?...", f"text, then {html}?..."),
+ ("bracket_punct", f"here ({url}).", f"here ({html})."),
+ ("punct_bracket", f"there [{url}?]", f"there [{html}?]"),
+ ("punct_bracket_punct", f"not here? ({url}!).", f"not here? ({html}!)."),
+ (
+ "multi_punct_bracket",
+ f"not there ({url}...);",
+ f"not there ({html}...);",
+ ),
+ ]
+ for desc, text, output in test_table:
+ with self.subTest(desc=desc):
+ self.assertEqual(views.status.format_links(text), output)
def test_format_links_special_chars(self, *_):
"""find and format urls into a tags"""
@@ -464,6 +468,13 @@ http://www.fish.com/"""
views.status.format_links(url), f'{url[8:]} '
)
+ def test_format_links_ignore_non_urls(self, *_):
+ """formating links should leave plain text untouced"""
+ text_elision = "> “The distinction is significant.” [...]" # bookwyrm#2993
+ text_quoteparens = "some kind of gene-editing technology (?)" # bookwyrm#3049
+ self.assertEqual(views.status.format_links(text_elision), text_elision)
+ self.assertEqual(views.status.format_links(text_quoteparens), text_quoteparens)
+
def test_format_mentions_with_at_symbol_links(self, *_):
"""A link with an @username shouldn't treat the username as a mention"""
content = "a link to https://example.com/user/@mouse"
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 0759012fe..8541f4fb6 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -600,6 +600,12 @@ urlpatterns = [
name="prompt-2fa",
),
re_path(r"^preferences/export/?$", views.Export.as_view(), name="prefs-export"),
+ re_path(r"^preferences/move/?$", views.MoveUser.as_view(), name="prefs-move"),
+ re_path(r"^preferences/alias/?$", views.AliasUser.as_view(), name="prefs-alias"),
+ re_path(
+ r"^preferences/remove-alias/?$", views.remove_alias, name="prefs-remove-alias"
+ ),
+ re_path(r"^preferences/unmove/?$", views.unmove, name="prefs-unmove"),
re_path(r"^preferences/delete/?$", views.DeleteUser.as_view(), name="prefs-delete"),
re_path(
r"^preferences/deactivate/?$",
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index 84060acb7..2d2e97f52 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -37,6 +37,7 @@ from .admin.user_admin import UserAdmin, UserAdminList, ActivateUserAdmin
from .preferences.change_password import ChangePassword
from .preferences.edit_user import EditUser
from .preferences.export import Export
+from .preferences.move_user import MoveUser, AliasUser, remove_alias, unmove
from .preferences.delete_user import DeleteUser, DeactivateUser, ReactivateUser
from .preferences.block import Block, unblock
from .preferences.two_factor_auth import (
diff --git a/bookwyrm/views/admin/celery_status.py b/bookwyrm/views/admin/celery_status.py
index cd8b85b6d..dbf18dac8 100644
--- a/bookwyrm/views/admin/celery_status.py
+++ b/bookwyrm/views/admin/celery_status.py
@@ -110,20 +110,20 @@ class ClearCeleryForm(forms.Form):
queues = forms.MultipleChoiceField(
label="Queues",
choices=[
- (LOW, "Low prioirty"),
+ (LOW, "Low priority"),
(MEDIUM, "Medium priority"),
(HIGH, "High priority"),
- (STREAMS, "Streams"),
- (IMAGES, "Images"),
- (SUGGESTED_USERS, "Suggested users"),
- (EMAIL, "Email"),
+ (BROADCAST, "Broadcast"),
(CONNECTORS, "Connectors"),
- (LISTS, "Lists"),
- (INBOX, "Inbox"),
+ (EMAIL, "Email"),
+ (IMAGES, "Images"),
(IMPORTS, "Imports"),
(IMPORT_TRIGGERED, "Import triggered"),
- (BROADCAST, "Broadcasts"),
+ (INBOX, "Inbox"),
+ (LISTS, "Lists"),
(MISC, "Misc"),
+ (STREAMS, "Streams"),
+ (SUGGESTED_USERS, "Suggested users"),
],
widget=forms.CheckboxSelectMultiple,
)
diff --git a/bookwyrm/views/preferences/move_user.py b/bookwyrm/views/preferences/move_user.py
new file mode 100644
index 000000000..93abf2f18
--- /dev/null
+++ b/bookwyrm/views/preferences/move_user.py
@@ -0,0 +1,111 @@
+""" move your account somewhere else """
+
+from django.core.exceptions import PermissionDenied
+from django.contrib.auth.decorators import login_required
+from django.shortcuts import get_object_or_404, redirect
+from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
+from django.views import View
+from django.views.decorators.http import require_POST
+
+from bookwyrm import forms, models
+from bookwyrm.views.helpers import handle_remote_webfinger
+
+
+# pylint: disable=no-self-use
+@method_decorator(login_required, name="dispatch")
+class MoveUser(View):
+ """move user view"""
+
+ def get(self, request):
+ """move page for a user"""
+ data = {
+ "form": forms.MoveUserForm(),
+ "user": request.user,
+ }
+ return TemplateResponse(request, "preferences/move_user.html", data)
+
+ def post(self, request):
+ """Packing your stuff and moving house"""
+ form = forms.MoveUserForm(request.POST, instance=request.user)
+ user = models.User.objects.get(id=request.user.id)
+
+ if form.is_valid() and user.check_password(form.cleaned_data["password"]):
+ username = form.cleaned_data["target"]
+ target = handle_remote_webfinger(username)
+
+ try:
+ models.MoveUser.objects.create(
+ user=request.user, object=request.user.remote_id, target=target
+ )
+
+ return redirect("user-feed", username=request.user.username)
+
+ except PermissionDenied:
+ form.errors["target"] = [
+ "Set this user as an alias on the user you are moving to first"
+ ]
+ data = {"form": form, "user": request.user}
+ return TemplateResponse(request, "preferences/move_user.html", data)
+
+ form.errors["password"] = ["Invalid password"]
+ data = {"form": form, "user": request.user}
+ return TemplateResponse(request, "preferences/move_user.html", data)
+
+
+# pylint: disable=no-self-use
+@method_decorator(login_required, name="dispatch")
+class AliasUser(View):
+ """alias user view"""
+
+ def get(self, request):
+ """move page for a user"""
+ data = {
+ "form": forms.AliasUserForm(),
+ "user": request.user,
+ }
+ return TemplateResponse(request, "preferences/alias_user.html", data)
+
+ def post(self, request):
+ """Creating a nom de plume"""
+ form = forms.AliasUserForm(request.POST, instance=request.user)
+ user = models.User.objects.get(id=request.user.id)
+
+ if form.is_valid() and user.check_password(form.cleaned_data["password"]):
+ username = form.cleaned_data["username"]
+ remote_user = handle_remote_webfinger(username)
+
+ if remote_user is None:
+ form.errors["username"] = ["Username does not exist"]
+ data = {"form": form, "user": request.user}
+ return TemplateResponse(request, "preferences/alias_user.html", data)
+
+ user.also_known_as.add(remote_user.id)
+
+ return redirect("prefs-alias")
+
+ form.errors["password"] = ["Invalid password"]
+ data = {"form": form, "user": request.user}
+ return TemplateResponse(request, "preferences/alias_user.html", data)
+
+
+@login_required
+@require_POST
+def remove_alias(request):
+ """remove an alias from the user profile"""
+
+ request.user.also_known_as.remove(request.POST["alias"])
+ return redirect("prefs-alias")
+
+
+@require_POST
+@login_required
+def unmove(request):
+ """undo a user move"""
+ target = get_object_or_404(models.User, remote_id=request.POST["remote_id"])
+ move = get_object_or_404(models.MoveUser, target=target, user=request.user)
+ move.delete()
+
+ request.user.moved_to = None
+ request.user.save(update_fields=["moved_to"], broadcast=True)
+ return redirect("prefs-alias")
diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py
index 7a0517b01..34b62d0b4 100644
--- a/bookwyrm/views/status.py
+++ b/bookwyrm/views/status.py
@@ -1,7 +1,6 @@
""" what are we here for if not for posting """
import re
import logging
-from urllib.parse import urlparse
from django.contrib.auth.decorators import login_required
from django.core.validators import URLValidator
@@ -297,65 +296,51 @@ def find_or_create_hashtags(content):
def format_links(content):
"""detect and format links"""
- validator = URLValidator()
- formatted_content = ""
+ validator = URLValidator(["http", "https"])
+ schema_re = re.compile(r"\bhttps?://")
split_content = re.split(r"(\s+)", content)
- for potential_link in split_content:
- if not potential_link:
+ for i, potential_link in enumerate(split_content):
+ if not schema_re.search(potential_link):
continue
- wrapped = _wrapped(potential_link)
- if wrapped:
- wrapper_close = potential_link[-1]
- formatted_content += potential_link[0]
- potential_link = potential_link[1:-1]
-
- ends_with_punctuation = _ends_with_punctuation(potential_link)
- if ends_with_punctuation:
- punctuation_glyph = potential_link[-1]
- potential_link = potential_link[0:-1]
+ # Strip surrounding brackets and trailing punctuation.
+ prefix, potential_link, suffix = _unwrap(potential_link)
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 += f'{link} '
+ link = schema_re.sub("", potential_link)
+ split_content[i] = f'{prefix}{link} {suffix}'
except (ValidationError, UnicodeError):
- formatted_content += potential_link
+ pass
- if wrapped:
- formatted_content += wrapper_close
-
- if ends_with_punctuation:
- formatted_content += punctuation_glyph
-
- return formatted_content
+ return "".join(split_content)
-def _wrapped(text):
- """check if a line of text is wrapped"""
- wrappers = [("(", ")"), ("[", "]"), ("{", "}")]
- for wrapper in wrappers:
+def _unwrap(text):
+ """split surrounding brackets and trailing punctuation from a string of text"""
+ punct = re.compile(r'([.,;:!?"’”»]+)$')
+ prefix = suffix = ""
+
+ if punct.search(text):
+ # Move punctuation to suffix segment.
+ text, suffix, _ = punct.split(text)
+
+ for wrapper in ("()", "[]", "{}"):
if text[0] == wrapper[0] and text[-1] == wrapper[-1]:
- return True
- return False
+ # Split out wrapping chars.
+ suffix = text[-1] + suffix
+ prefix, text = text[:1], text[1:-1]
+ break # Nested wrappers not supported atm.
+ if punct.search(text):
+ # Move inner punctuation to suffix segment.
+ text, inner_punct, _ = punct.split(text)
+ suffix = inner_punct + suffix
-def _ends_with_punctuation(text):
- """check if a line of text ends with a punctuation glyph"""
- glyphs = [".", ",", ";", ":", "!", "?", "”", "’", '"', "»"]
- for glyph in glyphs:
- if text[-1] == glyph:
- return True
- return False
+ return prefix, text, suffix
def to_markdown(content):
diff --git a/bookwyrm/views/wellknown.py b/bookwyrm/views/wellknown.py
index ec5acf98f..0f2805ff2 100644
--- a/bookwyrm/views/wellknown.py
+++ b/bookwyrm/views/wellknown.py
@@ -21,6 +21,7 @@ def webfinger(request):
username = resource.replace("acct:", "")
user = get_object_or_404(models.User, username__iexact=username)
+ href = user.moved_to if user.moved_to else user.remote_id
return JsonResponse(
{
@@ -29,7 +30,7 @@ def webfinger(request):
{
"rel": "self",
"type": "application/activity+json",
- "href": user.remote_id,
+ "href": href,
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
diff --git a/locale/ca_ES/LC_MESSAGES/django.mo b/locale/ca_ES/LC_MESSAGES/django.mo
index f62f704e5..a9b338a2a 100644
Binary files a/locale/ca_ES/LC_MESSAGES/django.mo and b/locale/ca_ES/LC_MESSAGES/django.mo differ
diff --git a/locale/ca_ES/LC_MESSAGES/django.po b/locale/ca_ES/LC_MESSAGES/django.po
index 6a58b0720..d5e96e0d1 100644
--- a/locale/ca_ES/LC_MESSAGES/django.po
+++ b/locale/ca_ES/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 06:50\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-11 06:52\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Catalan\n"
"Language: ca\n"
@@ -1372,8 +1372,8 @@ msgstr "Edicions de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edicions de \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr "Edicions de \"%(work_title)s\" "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,15 +2805,10 @@ msgstr "Fitxer CSV no vàlid"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] "\n"
-"Actualment, es permet la importació de %(display_size)s llibres cada %(import_limit_reset)s dies. "
-msgstr[1] ""
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] ""
+msgstr[1] "Actualment, se't permet la importació de %(import_size_limit)s llibres cada %(import_limit_reset)s dies."
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po
index baf448c10..63cdbd8fc 100644
--- a/locale/de_DE/LC_MESSAGES/django.po
+++ b/locale/de_DE/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 16:03\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: German\n"
"Language: de\n"
@@ -1372,8 +1372,8 @@ msgstr "Ausgaben von %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Ausgaben von \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,15 +2805,10 @@ msgstr "Keine gültige CSV-Datei"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
-msgstr[1] "\n"
-"Momentan darfst du alle %(import_limit_reset)s Tage %(import_size_limit)s Bücher importieren. "
+msgstr[1] ""
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po
index 60fd2463e..e1196a49b 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: 2023-10-02 16:40+0000\n"
+"POT-Creation-Date: 2023-11-02 21:32+0000\n"
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: English \n"
@@ -43,15 +43,15 @@ msgstr ""
msgid "Unlimited"
msgstr ""
-#: bookwyrm/forms/edit_user.py:88
+#: bookwyrm/forms/edit_user.py:104
msgid "Incorrect password"
msgstr ""
-#: bookwyrm/forms/edit_user.py:95 bookwyrm/forms/landing.py:90
+#: bookwyrm/forms/edit_user.py:111 bookwyrm/forms/landing.py:90
msgid "Password does not match"
msgstr ""
-#: bookwyrm/forms/edit_user.py:118
+#: bookwyrm/forms/edit_user.py:134
msgid "Incorrect Password"
msgstr ""
@@ -103,8 +103,8 @@ msgstr ""
msgid "Book Title"
msgstr ""
-#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:156
-#: bookwyrm/templates/shelf/shelf.html:188
+#: bookwyrm/forms/lists.py:28 bookwyrm/templates/shelf/shelf.html:171
+#: bookwyrm/templates/shelf/shelf.html:203
#: bookwyrm/templates/snippets/create_status/review.html:32
msgid "Rating"
msgstr ""
@@ -146,7 +146,7 @@ msgstr ""
msgid "Automatically generated report"
msgstr ""
-#: bookwyrm/models/base_model.py:18 bookwyrm/models/import_job.py:47
+#: bookwyrm/models/base_model.py:18 bookwyrm/models/import_job.py:48
#: bookwyrm/models/link.py:72 bookwyrm/templates/import/import_status.html:214
#: bookwyrm/templates/settings/link_domains/link_domains.html:19
msgid "Pending"
@@ -172,23 +172,23 @@ msgstr ""
msgid "Domain block"
msgstr ""
-#: bookwyrm/models/book.py:283
+#: bookwyrm/models/book.py:282
msgid "Audiobook"
msgstr ""
-#: bookwyrm/models/book.py:284
+#: bookwyrm/models/book.py:283
msgid "eBook"
msgstr ""
-#: bookwyrm/models/book.py:285
+#: bookwyrm/models/book.py:284
msgid "Graphic novel"
msgstr ""
-#: bookwyrm/models/book.py:286
+#: bookwyrm/models/book.py:285
msgid "Hardcover"
msgstr ""
-#: bookwyrm/models/book.py:287
+#: bookwyrm/models/book.py:286
msgid "Paperback"
msgstr ""
@@ -206,26 +206,26 @@ msgstr ""
msgid "Blocked"
msgstr ""
-#: bookwyrm/models/fields.py:29
+#: bookwyrm/models/fields.py:30
#, python-format
msgid "%(value)s is not a valid remote_id"
msgstr ""
-#: bookwyrm/models/fields.py:38 bookwyrm/models/fields.py:47
+#: bookwyrm/models/fields.py:39 bookwyrm/models/fields.py:48
#, python-format
msgid "%(value)s is not a valid username"
msgstr ""
-#: bookwyrm/models/fields.py:192 bookwyrm/templates/layout.html:128
+#: bookwyrm/models/fields.py:193 bookwyrm/templates/layout.html:129
#: bookwyrm/templates/ostatus/error.html:29
msgid "username"
msgstr ""
-#: bookwyrm/models/fields.py:197
+#: bookwyrm/models/fields.py:198
msgid "A user with that username already exists."
msgstr ""
-#: bookwyrm/models/fields.py:216
+#: bookwyrm/models/fields.py:217
#: bookwyrm/templates/snippets/privacy-icons.html:3
#: bookwyrm/templates/snippets/privacy-icons.html:4
#: bookwyrm/templates/snippets/privacy_select.html:11
@@ -233,7 +233,7 @@ msgstr ""
msgid "Public"
msgstr ""
-#: bookwyrm/models/fields.py:217
+#: bookwyrm/models/fields.py:218
#: bookwyrm/templates/snippets/privacy-icons.html:7
#: bookwyrm/templates/snippets/privacy-icons.html:8
#: bookwyrm/templates/snippets/privacy_select.html:14
@@ -241,7 +241,7 @@ msgstr ""
msgid "Unlisted"
msgstr ""
-#: bookwyrm/models/fields.py:218
+#: bookwyrm/models/fields.py:219
#: bookwyrm/templates/snippets/privacy_select.html:17
#: bookwyrm/templates/user/relationships/followers.html:6
#: bookwyrm/templates/user/relationships/followers.html:11
@@ -250,7 +250,7 @@ msgstr ""
msgid "Followers"
msgstr ""
-#: bookwyrm/models/fields.py:219
+#: bookwyrm/models/fields.py:220
#: bookwyrm/templates/snippets/create_status/post_options_block.html:6
#: bookwyrm/templates/snippets/privacy-icons.html:15
#: bookwyrm/templates/snippets/privacy-icons.html:16
@@ -259,30 +259,30 @@ msgstr ""
msgid "Private"
msgstr ""
-#: bookwyrm/models/import_job.py:48 bookwyrm/templates/import/import.html:174
+#: bookwyrm/models/import_job.py:49 bookwyrm/templates/import/import.html:174
#: bookwyrm/templates/settings/imports/imports.html:98
-#: bookwyrm/templates/settings/users/user_admin.html:81
-#: bookwyrm/templates/settings/users/user_info.html:28
+#: bookwyrm/templates/settings/users/user_admin.html:87
+#: bookwyrm/templates/settings/users/user_info.html:33
msgid "Active"
msgstr ""
-#: bookwyrm/models/import_job.py:49 bookwyrm/templates/import/import.html:172
+#: bookwyrm/models/import_job.py:50 bookwyrm/templates/import/import.html:172
msgid "Complete"
msgstr ""
-#: bookwyrm/models/import_job.py:50
+#: bookwyrm/models/import_job.py:51
msgid "Stopped"
msgstr ""
-#: bookwyrm/models/import_job.py:83 bookwyrm/models/import_job.py:91
+#: bookwyrm/models/import_job.py:84 bookwyrm/models/import_job.py:92
msgid "Import stopped"
msgstr ""
-#: bookwyrm/models/import_job.py:363 bookwyrm/models/import_job.py:388
+#: bookwyrm/models/import_job.py:356 bookwyrm/models/import_job.py:381
msgid "Error loading book"
msgstr ""
-#: bookwyrm/models/import_job.py:372
+#: bookwyrm/models/import_job.py:365
msgid "Could not find a match for book"
msgstr ""
@@ -369,103 +369,103 @@ msgstr ""
msgid "Everything else"
msgstr ""
-#: bookwyrm/settings.py:223
+#: bookwyrm/settings.py:230
msgid "Home Timeline"
msgstr ""
-#: bookwyrm/settings.py:223
+#: bookwyrm/settings.py:230
msgid "Home"
msgstr ""
-#: bookwyrm/settings.py:224
+#: bookwyrm/settings.py:231
msgid "Books Timeline"
msgstr ""
-#: bookwyrm/settings.py:224
+#: bookwyrm/settings.py:231
#: bookwyrm/templates/guided_tour/user_profile.html:101
#: bookwyrm/templates/search/layout.html:22
#: bookwyrm/templates/search/layout.html:43
-#: bookwyrm/templates/user/layout.html:97
+#: bookwyrm/templates/user/layout.html:112
msgid "Books"
msgstr ""
-#: bookwyrm/settings.py:296
+#: bookwyrm/settings.py:303
msgid "English"
msgstr ""
-#: bookwyrm/settings.py:297
+#: bookwyrm/settings.py:304
msgid "Català (Catalan)"
msgstr ""
-#: bookwyrm/settings.py:298
+#: bookwyrm/settings.py:305
msgid "Deutsch (German)"
msgstr ""
-#: bookwyrm/settings.py:299
+#: bookwyrm/settings.py:306
msgid "Esperanto (Esperanto)"
msgstr ""
-#: bookwyrm/settings.py:300
+#: bookwyrm/settings.py:307
msgid "Español (Spanish)"
msgstr ""
-#: bookwyrm/settings.py:301
+#: bookwyrm/settings.py:308
msgid "Euskara (Basque)"
msgstr ""
-#: bookwyrm/settings.py:302
+#: bookwyrm/settings.py:309
msgid "Galego (Galician)"
msgstr ""
-#: bookwyrm/settings.py:303
+#: bookwyrm/settings.py:310
msgid "Italiano (Italian)"
msgstr ""
-#: bookwyrm/settings.py:304
+#: bookwyrm/settings.py:311
msgid "Suomi (Finnish)"
msgstr ""
-#: bookwyrm/settings.py:305
+#: bookwyrm/settings.py:312
msgid "Français (French)"
msgstr ""
-#: bookwyrm/settings.py:306
+#: bookwyrm/settings.py:313
msgid "Lietuvių (Lithuanian)"
msgstr ""
-#: bookwyrm/settings.py:307
+#: bookwyrm/settings.py:314
msgid "Nederlands (Dutch)"
msgstr ""
-#: bookwyrm/settings.py:308
+#: bookwyrm/settings.py:315
msgid "Norsk (Norwegian)"
msgstr ""
-#: bookwyrm/settings.py:309
+#: bookwyrm/settings.py:316
msgid "Polski (Polish)"
msgstr ""
-#: bookwyrm/settings.py:310
+#: bookwyrm/settings.py:317
msgid "Português do Brasil (Brazilian Portuguese)"
msgstr ""
-#: bookwyrm/settings.py:311
+#: bookwyrm/settings.py:318
msgid "Português Europeu (European Portuguese)"
msgstr ""
-#: bookwyrm/settings.py:312
+#: bookwyrm/settings.py:319
msgid "Română (Romanian)"
msgstr ""
-#: bookwyrm/settings.py:313
+#: bookwyrm/settings.py:320
msgid "Svenska (Swedish)"
msgstr ""
-#: bookwyrm/settings.py:314
+#: bookwyrm/settings.py:321
msgid "简体中文 (Simplified Chinese)"
msgstr ""
-#: bookwyrm/settings.py:315
+#: bookwyrm/settings.py:322
msgid "繁體中文 (Traditional Chinese)"
msgstr ""
@@ -576,7 +576,7 @@ msgid "Software version:"
msgstr ""
#: bookwyrm/templates/about/layout.html:30
-#: bookwyrm/templates/embed-layout.html:33
+#: bookwyrm/templates/embed-layout.html:34
#: bookwyrm/templates/snippets/footer.html:8
#, python-format
msgid "About %(site_name)s"
@@ -681,7 +681,7 @@ msgstr ""
#: bookwyrm/templates/annual_summary/layout.html:157
#: bookwyrm/templates/annual_summary/layout.html:178
#: bookwyrm/templates/annual_summary/layout.html:247
-#: bookwyrm/templates/book/book.html:63
+#: bookwyrm/templates/book/book.html:65
#: bookwyrm/templates/discover/large-book.html:22
#: bookwyrm/templates/landing/large-book.html:26
#: bookwyrm/templates/landing/small-book.html:18
@@ -769,24 +769,24 @@ msgid "View ISNI record"
msgstr ""
#: bookwyrm/templates/author/author.html:95
-#: bookwyrm/templates/book/book.html:173
+#: bookwyrm/templates/book/book.html:175
msgid "View on ISFDB"
msgstr ""
#: bookwyrm/templates/author/author.html:100
#: bookwyrm/templates/author/sync_modal.html:5
-#: bookwyrm/templates/book/book.html:140
+#: bookwyrm/templates/book/book.html:142
#: bookwyrm/templates/book/sync_modal.html:5
msgid "Load data"
msgstr ""
#: bookwyrm/templates/author/author.html:104
-#: bookwyrm/templates/book/book.html:144
+#: bookwyrm/templates/book/book.html:146
msgid "View on OpenLibrary"
msgstr ""
#: bookwyrm/templates/author/author.html:119
-#: bookwyrm/templates/book/book.html:158
+#: bookwyrm/templates/book/book.html:160
msgid "View on Inventaire"
msgstr ""
@@ -798,11 +798,7 @@ msgstr ""
msgid "View on Goodreads"
msgstr ""
-#: bookwyrm/templates/author/author.html:151
-msgid "View ISFDB entry"
-msgstr ""
-
-#: bookwyrm/templates/author/author.html:166
+#: bookwyrm/templates/author/author.html:158
#, python-format
msgid "Books by %(name)s"
msgstr ""
@@ -960,19 +956,19 @@ msgstr ""
msgid "Unable to connect to remote source."
msgstr ""
-#: bookwyrm/templates/book/book.html:71 bookwyrm/templates/book/book.html:72
+#: bookwyrm/templates/book/book.html:73 bookwyrm/templates/book/book.html:74
msgid "Edit Book"
msgstr ""
-#: bookwyrm/templates/book/book.html:97 bookwyrm/templates/book/book.html:100
+#: bookwyrm/templates/book/book.html:99 bookwyrm/templates/book/book.html:102
msgid "Click to add cover"
msgstr ""
-#: bookwyrm/templates/book/book.html:106
+#: bookwyrm/templates/book/book.html:108
msgid "Failed to load cover"
msgstr ""
-#: bookwyrm/templates/book/book.html:117
+#: bookwyrm/templates/book/book.html:119
msgid "Click to enlarge"
msgstr ""
@@ -1047,13 +1043,13 @@ msgstr ""
#: bookwyrm/templates/guided_tour/lists.html:14
#: bookwyrm/templates/guided_tour/user_books.html:102
#: bookwyrm/templates/guided_tour/user_profile.html:78
-#: bookwyrm/templates/layout.html:90 bookwyrm/templates/lists/curate.html:8
+#: bookwyrm/templates/layout.html:91 bookwyrm/templates/lists/curate.html:8
#: bookwyrm/templates/lists/list.html:12 bookwyrm/templates/lists/lists.html:5
#: bookwyrm/templates/lists/lists.html:12
#: bookwyrm/templates/search/layout.html:26
#: bookwyrm/templates/search/layout.html:51
#: bookwyrm/templates/settings/celery.html:77
-#: bookwyrm/templates/user/layout.html:91 bookwyrm/templates/user/lists.html:6
+#: bookwyrm/templates/user/layout.html:106 bookwyrm/templates/user/lists.html:6
msgid "Lists"
msgstr ""
@@ -1118,7 +1114,7 @@ msgstr ""
#: bookwyrm/templates/book/cover_add_modal.html:23
#: bookwyrm/templates/book/edit/edit_book_form.html:250
-msgid "Load cover from url:"
+msgid "Load cover from URL:"
msgstr ""
#: bookwyrm/templates/book/cover_show_modal.html:6
@@ -1329,7 +1325,7 @@ msgid "Add Another Author"
msgstr ""
#: bookwyrm/templates/book/edit/edit_book_form.html:231
-#: bookwyrm/templates/shelf/shelf.html:147
+#: bookwyrm/templates/shelf/shelf.html:162
msgid "Cover"
msgstr ""
@@ -1530,22 +1526,22 @@ msgstr ""
msgid "%(languages)s language"
msgstr ""
-#: bookwyrm/templates/book/publisher_info.html:65
+#: bookwyrm/templates/book/publisher_info.html:63
#, python-format
msgid "Published %(date)s by %(publisher)s."
msgstr ""
+#: bookwyrm/templates/book/publisher_info.html:65
+#, python-format
+msgid "Published by %(publisher)s."
+msgstr ""
+
#: bookwyrm/templates/book/publisher_info.html:67
#, python-format
msgid "Published %(date)s"
msgstr ""
-#: bookwyrm/templates/book/publisher_info.html:69
-#, python-format
-msgid "Published by %(publisher)s."
-msgstr ""
-
-#: bookwyrm/templates/book/rating.html:13
+#: bookwyrm/templates/book/rating.html:19
msgid "rated it"
msgstr ""
@@ -1553,12 +1549,12 @@ msgstr ""
msgid "Series by"
msgstr ""
-#: bookwyrm/templates/book/series.html:27
+#: bookwyrm/templates/book/series.html:28
#, python-format
msgid "Book %(series_number)s"
msgstr ""
-#: bookwyrm/templates/book/series.html:27
+#: bookwyrm/templates/book/series.html:28
msgid "Unsorted Book"
msgstr ""
@@ -1588,7 +1584,7 @@ msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
-#: bookwyrm/templates/settings/users/user_info.html:92
+#: bookwyrm/templates/settings/users/user_info.html:98
msgid "Confirmation code:"
msgstr ""
@@ -1682,6 +1678,7 @@ msgstr ""
#: bookwyrm/templates/ostatus/subscribe.html:42
#: bookwyrm/templates/ostatus/success.html:17
#: bookwyrm/templates/ostatus/success.html:18
+#: bookwyrm/templates/user/moved.html:19 bookwyrm/templates/user/moved.html:20
#: bookwyrm/templates/user/user_preview.html:16
#: bookwyrm/templates/user/user_preview.html:17
msgid "Locked account"
@@ -1756,7 +1753,7 @@ msgstr ""
#: bookwyrm/templates/discover/discover.html:4
#: bookwyrm/templates/discover/discover.html:10
-#: bookwyrm/templates/layout.html:93
+#: bookwyrm/templates/layout.html:94
msgid "Discover"
msgstr ""
@@ -1888,20 +1885,20 @@ msgstr ""
msgid "Test email"
msgstr ""
-#: bookwyrm/templates/embed-layout.html:20 bookwyrm/templates/layout.html:31
-#: bookwyrm/templates/setup/layout.html:15
+#: bookwyrm/templates/embed-layout.html:21 bookwyrm/templates/layout.html:33
+#: bookwyrm/templates/layout.html:163 bookwyrm/templates/setup/layout.html:15
#: bookwyrm/templates/two_factor_auth/two_factor_login.html:18
#: bookwyrm/templates/two_factor_auth/two_factor_prompt.html:18
#, python-format
msgid "%(site_name)s home page"
msgstr ""
-#: bookwyrm/templates/embed-layout.html:39
+#: bookwyrm/templates/embed-layout.html:40
#: bookwyrm/templates/snippets/footer.html:12
msgid "Contact site admin"
msgstr ""
-#: bookwyrm/templates/embed-layout.html:45
+#: bookwyrm/templates/embed-layout.html:46
msgid "Join BookWyrm"
msgstr ""
@@ -1997,19 +1994,19 @@ msgid "Add to your books"
msgstr ""
#: bookwyrm/templates/get_started/book_preview.html:10
-#: bookwyrm/templates/shelf/shelf.html:86 bookwyrm/templates/user/user.html:37
+#: bookwyrm/templates/shelf/shelf.html:101 bookwyrm/templates/user/user.html:37
#: bookwyrm/templatetags/shelf_tags.py:14
msgid "To Read"
msgstr ""
#: bookwyrm/templates/get_started/book_preview.html:11
-#: bookwyrm/templates/shelf/shelf.html:87 bookwyrm/templates/user/user.html:38
+#: bookwyrm/templates/shelf/shelf.html:102 bookwyrm/templates/user/user.html:38
#: bookwyrm/templatetags/shelf_tags.py:15
msgid "Currently Reading"
msgstr ""
#: bookwyrm/templates/get_started/book_preview.html:12
-#: bookwyrm/templates/shelf/shelf.html:88
+#: bookwyrm/templates/shelf/shelf.html:103
#: bookwyrm/templates/snippets/shelf_selector.html:46
#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12
@@ -2018,7 +2015,7 @@ msgid "Read"
msgstr ""
#: bookwyrm/templates/get_started/book_preview.html:13
-#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:40
+#: bookwyrm/templates/shelf/shelf.html:104 bookwyrm/templates/user/user.html:40
#: bookwyrm/templatetags/shelf_tags.py:17
msgid "Stopped Reading"
msgstr ""
@@ -2028,7 +2025,7 @@ msgid "What are you reading?"
msgstr ""
#: bookwyrm/templates/get_started/books.html:9
-#: bookwyrm/templates/layout.html:39 bookwyrm/templates/lists/list.html:213
+#: bookwyrm/templates/layout.html:41 bookwyrm/templates/lists/list.html:213
msgid "Search for a book"
msgstr ""
@@ -2047,8 +2044,8 @@ msgstr ""
#: bookwyrm/templates/get_started/users.html:18
#: bookwyrm/templates/get_started/users.html:19
#: bookwyrm/templates/groups/members.html:15
-#: bookwyrm/templates/groups/members.html:16 bookwyrm/templates/layout.html:45
-#: bookwyrm/templates/layout.html:46 bookwyrm/templates/lists/list.html:217
+#: bookwyrm/templates/groups/members.html:16 bookwyrm/templates/layout.html:47
+#: bookwyrm/templates/layout.html:48 bookwyrm/templates/lists/list.html:217
#: bookwyrm/templates/search/layout.html:5
#: bookwyrm/templates/search/layout.html:10
#: bookwyrm/templates/search/layout.html:32
@@ -2539,8 +2536,8 @@ msgid "The bell will light up when you have a new notification. When it does, cl
msgstr ""
#: bookwyrm/templates/guided_tour/home.html:177
-#: bookwyrm/templates/layout.html:75 bookwyrm/templates/layout.html:106
-#: bookwyrm/templates/layout.html:107
+#: bookwyrm/templates/layout.html:77 bookwyrm/templates/layout.html:107
+#: bookwyrm/templates/layout.html:108
#: bookwyrm/templates/notifications/notifications_page.html:5
#: bookwyrm/templates/notifications/notifications_page.html:10
msgid "Notifications"
@@ -2703,7 +2700,8 @@ msgstr ""
#: bookwyrm/templates/guided_tour/user_groups.html:11
#: bookwyrm/templates/guided_tour/user_profile.html:55
-#: bookwyrm/templates/user/groups.html:6 bookwyrm/templates/user/layout.html:85
+#: bookwyrm/templates/user/groups.html:6
+#: bookwyrm/templates/user/layout.html:100
msgid "Groups"
msgstr ""
@@ -2748,7 +2746,7 @@ msgid "This is your user profile. All your latest activities will be listed here
msgstr ""
#: bookwyrm/templates/guided_tour/user_profile.html:11
-#: bookwyrm/templates/user/layout.html:19 bookwyrm/templates/user/user.html:14
+#: bookwyrm/templates/user/layout.html:20 bookwyrm/templates/user/user.html:14
msgid "User Profile"
msgstr ""
@@ -2757,7 +2755,7 @@ msgid "This tab shows everything you have read towards your annual reading goal,
msgstr ""
#: bookwyrm/templates/guided_tour/user_profile.html:32
-#: bookwyrm/templates/user/goal.html:6 bookwyrm/templates/user/layout.html:79
+#: bookwyrm/templates/user/goal.html:6 bookwyrm/templates/user/layout.html:94
msgid "Reading Goal"
msgstr ""
@@ -2796,7 +2794,7 @@ msgstr ""
#: bookwyrm/templates/import/import.html:5
#: bookwyrm/templates/import/import.html:9
-#: bookwyrm/templates/shelf/shelf.html:64
+#: bookwyrm/templates/shelf/shelf.html:79
msgid "Import Books"
msgstr ""
@@ -2807,7 +2805,7 @@ msgstr ""
#: bookwyrm/templates/import/import.html:21
#, python-format
msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
-msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgid_plural "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
@@ -2868,7 +2866,7 @@ msgstr ""
#: bookwyrm/templates/import/import.html:106
#: bookwyrm/templates/import/import.html:108
-#: bookwyrm/templates/preferences/layout.html:35
+#: bookwyrm/templates/preferences/layout.html:43
#: bookwyrm/templates/settings/federation/instance_blocklist.html:78
msgid "Import"
msgstr ""
@@ -2967,8 +2965,8 @@ msgid "Row"
msgstr ""
#: bookwyrm/templates/import/import_status.html:110
-#: bookwyrm/templates/shelf/shelf.html:148
-#: bookwyrm/templates/shelf/shelf.html:170
+#: bookwyrm/templates/shelf/shelf.html:163
+#: bookwyrm/templates/shelf/shelf.html:185
msgid "Title"
msgstr ""
@@ -2981,8 +2979,8 @@ msgid "Openlibrary key"
msgstr ""
#: bookwyrm/templates/import/import_status.html:121
-#: bookwyrm/templates/shelf/shelf.html:149
-#: bookwyrm/templates/shelf/shelf.html:173
+#: bookwyrm/templates/shelf/shelf.html:164
+#: bookwyrm/templates/shelf/shelf.html:188
msgid "Author"
msgstr ""
@@ -3139,7 +3137,7 @@ msgid "Login"
msgstr ""
#: bookwyrm/templates/landing/login.html:7
-#: bookwyrm/templates/landing/login.html:36 bookwyrm/templates/layout.html:136
+#: bookwyrm/templates/landing/login.html:36 bookwyrm/templates/layout.html:142
#: bookwyrm/templates/ostatus/error.html:37
msgid "Log in"
msgstr ""
@@ -3150,7 +3148,7 @@ msgstr ""
#: bookwyrm/templates/landing/login.html:21
#: bookwyrm/templates/landing/reactivate.html:17
-#: bookwyrm/templates/layout.html:127 bookwyrm/templates/ostatus/error.html:28
+#: bookwyrm/templates/layout.html:128 bookwyrm/templates/ostatus/error.html:28
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr ""
@@ -3158,13 +3156,13 @@ msgstr ""
#: bookwyrm/templates/landing/login.html:27
#: bookwyrm/templates/landing/password_reset.html:26
#: bookwyrm/templates/landing/reactivate.html:23
-#: bookwyrm/templates/layout.html:131 bookwyrm/templates/ostatus/error.html:32
+#: bookwyrm/templates/layout.html:132 bookwyrm/templates/ostatus/error.html:32
#: bookwyrm/templates/preferences/2fa.html:91
#: bookwyrm/templates/snippets/register_form.html:45
msgid "Password:"
msgstr ""
-#: bookwyrm/templates/landing/login.html:39 bookwyrm/templates/layout.html:133
+#: bookwyrm/templates/landing/login.html:39 bookwyrm/templates/layout.html:139
#: bookwyrm/templates/ostatus/error.html:34
msgid "Forgot your password?"
msgstr ""
@@ -3207,35 +3205,39 @@ msgstr ""
msgid "%(site_name)s search"
msgstr ""
-#: bookwyrm/templates/layout.html:37
+#: bookwyrm/templates/layout.html:39
msgid "Search for a book, user, or list"
msgstr ""
-#: bookwyrm/templates/layout.html:52 bookwyrm/templates/layout.html:53
+#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55
msgid "Scan Barcode"
msgstr ""
-#: bookwyrm/templates/layout.html:67
+#: bookwyrm/templates/layout.html:69
msgid "Main navigation menu"
msgstr ""
-#: bookwyrm/templates/layout.html:87
+#: bookwyrm/templates/layout.html:88
msgid "Feed"
msgstr ""
-#: bookwyrm/templates/layout.html:132 bookwyrm/templates/ostatus/error.html:33
+#: bookwyrm/templates/layout.html:134 bookwyrm/templates/ostatus/error.html:33
msgid "password"
msgstr ""
-#: bookwyrm/templates/layout.html:144
+#: bookwyrm/templates/layout.html:136
+msgid "Show/Hide password"
+msgstr ""
+
+#: bookwyrm/templates/layout.html:150
msgid "Join"
msgstr ""
-#: bookwyrm/templates/layout.html:179
+#: bookwyrm/templates/layout.html:196
msgid "Successfully posted status"
msgstr ""
-#: bookwyrm/templates/layout.html:180
+#: bookwyrm/templates/layout.html:197
msgid "Error posting status"
msgstr ""
@@ -3494,6 +3496,23 @@ msgstr ""
msgid "Saved Lists"
msgstr ""
+#: bookwyrm/templates/moved.html:27
+#, python-format
+msgid "You have moved your account to %(username)s "
+msgstr ""
+
+#: bookwyrm/templates/moved.html:32
+msgid "You can undo the move to restore full functionality, but some followers may have already unfollowed this account."
+msgstr ""
+
+#: bookwyrm/templates/moved.html:42 bookwyrm/templates/shelf/shelf.html:32
+msgid "Undo move"
+msgstr ""
+
+#: bookwyrm/templates/moved.html:46 bookwyrm/templates/user_menu.html:82
+msgid "Log out"
+msgstr ""
+
#: bookwyrm/templates/notifications/items/accept.html:18
#, python-format
msgid "%(related_user)s accepted your invitation to join group \"%(group_name)s \""
@@ -3745,6 +3764,16 @@ msgstr ""
msgid "%(related_user)s mentioned you in a status "
msgstr ""
+#: bookwyrm/templates/notifications/items/move_user.html:18
+#, python-format
+msgid "%(related_user)s has moved to %(username)s "
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/move_user.html:25
+#, python-format
+msgid "%(related_user)s has undone their move"
+msgstr ""
+
#: bookwyrm/templates/notifications/items/remove.html:17
#, python-format
msgid "has been removed from your group \"%(group_name)s \""
@@ -3783,7 +3812,7 @@ msgstr[0] ""
msgstr[1] ""
#: bookwyrm/templates/notifications/items/status_preview.html:4
-#: bookwyrm/templates/snippets/status/content_status.html:73
+#: bookwyrm/templates/snippets/status/content_status.html:62
msgid "Content warning"
msgstr ""
@@ -4001,9 +4030,51 @@ msgstr ""
msgid "Set up 2FA"
msgstr ""
+#: bookwyrm/templates/preferences/alias_user.html:4
+#: bookwyrm/templates/preferences/move_user.html:4
+#: bookwyrm/templates/preferences/move_user.html:7
+#: bookwyrm/templates/preferences/move_user.html:39
+msgid "Move Account"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:7
+#: bookwyrm/templates/preferences/alias_user.html:34
+msgid "Create Alias"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:12
+msgid "Add another account as an alias"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:16
+msgid "Marking another account as an alias is required if you want to move that account to this one."
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:19
+msgid "This is a reversable action and will not change the functionality of this account."
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:25
+msgid "Enter the username for the account you want to add as an alias e.g. user@example.com :"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:30
+#: bookwyrm/templates/preferences/move_user.html:35
+msgid "Confirm your password:"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:39
+#: bookwyrm/templates/preferences/layout.html:28
+msgid "Aliases"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:49
+msgid "Remove alias"
+msgstr ""
+
#: bookwyrm/templates/preferences/blocks.html:4
#: bookwyrm/templates/preferences/blocks.html:7
-#: bookwyrm/templates/preferences/layout.html:46
+#: bookwyrm/templates/preferences/layout.html:54
msgid "Blocked Users"
msgstr ""
@@ -4033,7 +4104,7 @@ msgstr ""
#: bookwyrm/templates/preferences/delete_user.html:4
#: bookwyrm/templates/preferences/delete_user.html:7
#: bookwyrm/templates/preferences/delete_user.html:40
-#: bookwyrm/templates/preferences/layout.html:28
+#: bookwyrm/templates/preferences/layout.html:36
#: bookwyrm/templates/settings/users/delete_user_form.html:22
msgid "Delete Account"
msgstr ""
@@ -4155,18 +4226,46 @@ msgstr ""
msgid "Account"
msgstr ""
-#: bookwyrm/templates/preferences/layout.html:31
-msgid "Data"
+#: bookwyrm/templates/preferences/layout.html:32
+msgid "Move Account"
msgstr ""
#: bookwyrm/templates/preferences/layout.html:39
+msgid "Data"
+msgstr ""
+
+#: bookwyrm/templates/preferences/layout.html:47
msgid "CSV export"
msgstr ""
-#: bookwyrm/templates/preferences/layout.html:42
+#: bookwyrm/templates/preferences/layout.html:50
msgid "Relationships"
msgstr ""
+#: bookwyrm/templates/preferences/move_user.html:12
+msgid "Migrate account to another server"
+msgstr ""
+
+#: bookwyrm/templates/preferences/move_user.html:16
+msgid "Moving your account will notify all your followers and direct them to follow the new account."
+msgstr ""
+
+#: bookwyrm/templates/preferences/move_user.html:19
+#, python-format
+msgid ""
+"\n"
+" %(user)s will be marked as moved and will not be discoverable or usable unless you undo the move.\n"
+" "
+msgstr ""
+
+#: bookwyrm/templates/preferences/move_user.html:25
+msgid "Remember to add this user as an alias of the target account before you try to move."
+msgstr ""
+
+#: bookwyrm/templates/preferences/move_user.html:30
+msgid "Enter the username for the account you want to move to e.g. user@example.com :"
+msgstr ""
+
#: bookwyrm/templates/reading_progress/finish.html:5
#, python-format
msgid "Finish \"%(book_title)s\""
@@ -4574,7 +4673,7 @@ msgid "Streams"
msgstr ""
#: bookwyrm/templates/settings/celery.html:32
-msgid "Broadcasts"
+msgid "Broadcast"
msgstr ""
#: bookwyrm/templates/settings/celery.html:38
@@ -4900,19 +4999,19 @@ msgstr ""
#: bookwyrm/templates/settings/federation/edit_instance.html:52
#: bookwyrm/templates/settings/federation/instance.html:46
-#: bookwyrm/templates/settings/users/user_info.html:113
+#: bookwyrm/templates/settings/users/user_info.html:119
msgid "Status:"
msgstr ""
#: bookwyrm/templates/settings/federation/edit_instance.html:66
#: bookwyrm/templates/settings/federation/instance.html:40
-#: bookwyrm/templates/settings/users/user_info.html:107
+#: bookwyrm/templates/settings/users/user_info.html:113
msgid "Software:"
msgstr ""
#: bookwyrm/templates/settings/federation/edit_instance.html:76
#: bookwyrm/templates/settings/federation/instance.html:43
-#: bookwyrm/templates/settings/users/user_info.html:110
+#: bookwyrm/templates/settings/users/user_info.html:116
msgid "Version:"
msgstr ""
@@ -4925,7 +5024,7 @@ msgid "Details"
msgstr ""
#: bookwyrm/templates/settings/federation/instance.html:53
-#: bookwyrm/templates/user/layout.html:69
+#: bookwyrm/templates/user/layout.html:84
msgid "Activity"
msgstr ""
@@ -4939,7 +5038,7 @@ msgid "View all"
msgstr ""
#: bookwyrm/templates/settings/federation/instance.html:62
-#: bookwyrm/templates/settings/users/user_info.html:60
+#: bookwyrm/templates/settings/users/user_info.html:66
msgid "Reports:"
msgstr ""
@@ -4956,7 +5055,7 @@ msgid "Blocked by us:"
msgstr ""
#: bookwyrm/templates/settings/federation/instance.html:90
-#: bookwyrm/templates/settings/users/user_info.html:117
+#: bookwyrm/templates/settings/users/user_info.html:123
msgid "Notes"
msgstr ""
@@ -5676,17 +5775,22 @@ msgstr ""
msgid "Remote instance"
msgstr ""
-#: bookwyrm/templates/settings/users/user_admin.html:86
+#: bookwyrm/templates/settings/users/user_admin.html:82
+#: bookwyrm/templates/settings/users/user_info.html:29
+msgid "Moved"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_admin.html:93
msgid "Deleted"
msgstr ""
-#: bookwyrm/templates/settings/users/user_admin.html:92
-#: bookwyrm/templates/settings/users/user_info.html:32
+#: bookwyrm/templates/settings/users/user_admin.html:99
+#: bookwyrm/templates/settings/users/user_info.html:38
msgid "Inactive"
msgstr ""
-#: bookwyrm/templates/settings/users/user_admin.html:101
-#: bookwyrm/templates/settings/users/user_info.html:127
+#: bookwyrm/templates/settings/users/user_admin.html:108
+#: bookwyrm/templates/settings/users/user_info.html:133
msgid "Not set"
msgstr ""
@@ -5698,55 +5802,55 @@ msgstr ""
msgid "Go to user admin"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:40
+#: bookwyrm/templates/settings/users/user_info.html:46
msgid "Local"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:42
+#: bookwyrm/templates/settings/users/user_info.html:48
msgid "Remote"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:51
+#: bookwyrm/templates/settings/users/user_info.html:57
msgid "User details"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:55
+#: bookwyrm/templates/settings/users/user_info.html:61
msgid "Email:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:65
+#: bookwyrm/templates/settings/users/user_info.html:71
msgid "(View reports)"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:71
+#: bookwyrm/templates/settings/users/user_info.html:77
msgid "Blocked by count:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:74
+#: bookwyrm/templates/settings/users/user_info.html:80
msgid "Date added:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:77
+#: bookwyrm/templates/settings/users/user_info.html:83
msgid "Last active date:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:80
+#: bookwyrm/templates/settings/users/user_info.html:86
msgid "Manually approved followers:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:83
+#: bookwyrm/templates/settings/users/user_info.html:89
msgid "Discoverable:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:87
+#: bookwyrm/templates/settings/users/user_info.html:93
msgid "Deactivation reason:"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:102
+#: bookwyrm/templates/settings/users/user_info.html:108
msgid "Instance details"
msgstr ""
-#: bookwyrm/templates/settings/users/user_info.html:124
+#: bookwyrm/templates/settings/users/user_info.html:130
msgid "View instance"
msgstr ""
@@ -5883,7 +5987,7 @@ msgid "Need help?"
msgstr ""
#: bookwyrm/templates/shelf/create_shelf_form.html:5
-#: bookwyrm/templates/shelf/shelf.html:72
+#: bookwyrm/templates/shelf/shelf.html:87
msgid "Create shelf"
msgstr ""
@@ -5891,58 +5995,66 @@ msgstr ""
msgid "Edit Shelf"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:24
+#: bookwyrm/templates/shelf/shelf.html:25
+msgid "You have have moved to"
+msgstr ""
+
+#: bookwyrm/templates/shelf/shelf.html:28
+msgid "You can undo this move to restore full functionality, but some followers may have already unfollowed this account."
+msgstr ""
+
+#: bookwyrm/templates/shelf/shelf.html:39
#: bookwyrm/templates/user/relationships/followers.html:18
#: bookwyrm/templates/user/relationships/following.html:18
msgid "User profile"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:39
+#: bookwyrm/templates/shelf/shelf.html:54
#: bookwyrm/templatetags/shelf_tags.py:13 bookwyrm/views/shelf/shelf.py:53
msgid "All books"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:97
+#: bookwyrm/templates/shelf/shelf.html:112
#, python-format
msgid "%(formatted_count)s book"
msgid_plural "%(formatted_count)s books"
msgstr[0] ""
msgstr[1] ""
-#: bookwyrm/templates/shelf/shelf.html:104
+#: bookwyrm/templates/shelf/shelf.html:119
#, python-format
msgid "(showing %(start)s-%(end)s)"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:116
+#: bookwyrm/templates/shelf/shelf.html:131
msgid "Edit shelf"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:124
+#: bookwyrm/templates/shelf/shelf.html:139
msgid "Delete shelf"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:152
-#: bookwyrm/templates/shelf/shelf.html:178
+#: bookwyrm/templates/shelf/shelf.html:167
+#: bookwyrm/templates/shelf/shelf.html:193
msgid "Shelved"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:153
-#: bookwyrm/templates/shelf/shelf.html:181
+#: bookwyrm/templates/shelf/shelf.html:168
+#: bookwyrm/templates/shelf/shelf.html:196
msgid "Started"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:154
-#: bookwyrm/templates/shelf/shelf.html:184
+#: bookwyrm/templates/shelf/shelf.html:169
+#: bookwyrm/templates/shelf/shelf.html:199
msgid "Finished"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:154
-#: bookwyrm/templates/shelf/shelf.html:184
+#: bookwyrm/templates/shelf/shelf.html:169
+#: bookwyrm/templates/shelf/shelf.html:199
msgid "Until"
msgstr ""
-#: bookwyrm/templates/shelf/shelf.html:210
+#: bookwyrm/templates/shelf/shelf.html:225
msgid "This shelf is empty."
msgstr ""
@@ -6248,6 +6360,10 @@ msgstr ""
msgid "%(username)s has read %(read_count)s of %(goal_count)s books ."
msgstr ""
+#: bookwyrm/templates/snippets/move_user_buttons.html:10
+msgid "Follow at new account"
+msgstr ""
+
#: bookwyrm/templates/snippets/page_text.html:8
#, python-format
msgid "page %(page)s of %(total_pages)s"
@@ -6389,35 +6505,35 @@ msgstr ""
msgid "Finish reading"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:80
+#: bookwyrm/templates/snippets/status/content_status.html:69
msgid "Show status"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:102
+#: bookwyrm/templates/snippets/status/content_status.html:91
#, python-format
msgid "(Page %(page)s"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:102
+#: bookwyrm/templates/snippets/status/content_status.html:91
#, python-format
msgid "%(endpage)s"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:104
+#: bookwyrm/templates/snippets/status/content_status.html:93
#, python-format
msgid "(%(percent)s%%"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:104
+#: bookwyrm/templates/snippets/status/content_status.html:93
#, python-format
msgid " - %(endpercent)s%%"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:127
+#: bookwyrm/templates/snippets/status/content_status.html:116
msgid "Open image in new window"
msgstr ""
-#: bookwyrm/templates/snippets/status/content_status.html:148
+#: bookwyrm/templates/snippets/status/content_status.html:137
msgid "Hide status"
msgstr ""
@@ -6609,10 +6725,14 @@ msgid "Groups: %(username)s"
msgstr ""
#: bookwyrm/templates/user/layout.html:50
+msgid "has moved to"
+msgstr ""
+
+#: bookwyrm/templates/user/layout.html:64
msgid "Follow Requests"
msgstr ""
-#: bookwyrm/templates/user/layout.html:73
+#: bookwyrm/templates/user/layout.html:88
#: bookwyrm/templates/user/reviews_comments.html:6
#: bookwyrm/templates/user/reviews_comments.html:12
msgid "Reviews and Comments"
@@ -6627,6 +6747,12 @@ msgstr ""
msgid "Create list"
msgstr ""
+#: bookwyrm/templates/user/moved.html:25
+#: bookwyrm/templates/user/user_preview.html:22
+#, python-format
+msgid "Joined %(date)s"
+msgstr ""
+
#: bookwyrm/templates/user/relationships/followers.html:31
#, python-format
msgid "%(username)s has no followers"
@@ -6698,11 +6824,6 @@ msgstr ""
msgid "No activities yet!"
msgstr ""
-#: bookwyrm/templates/user/user_preview.html:22
-#, python-format
-msgid "Joined %(date)s"
-msgstr ""
-
#: bookwyrm/templates/user/user_preview.html:26
#, python-format
msgid "%(display_count)s follower"
@@ -6730,10 +6851,6 @@ msgstr ""
msgid "View profile and more"
msgstr ""
-#: bookwyrm/templates/user_menu.html:82
-msgid "Log out"
-msgstr ""
-
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28
msgid "File exceeds maximum size: 10MB"
msgstr ""
@@ -6750,7 +6867,7 @@ msgid_plural "%(num)d books - by %(user)s"
msgstr[0] ""
msgstr[1] ""
-#: bookwyrm/templatetags/utilities.py:39
+#: bookwyrm/templatetags/utilities.py:48
#, python-format
msgid "%(title)s: %(subtitle)s"
msgstr ""
diff --git a/locale/eo_UY/LC_MESSAGES/django.mo b/locale/eo_UY/LC_MESSAGES/django.mo
index 1f66de56e..6795f2e82 100644
Binary files a/locale/eo_UY/LC_MESSAGES/django.mo and b/locale/eo_UY/LC_MESSAGES/django.mo differ
diff --git a/locale/eo_UY/LC_MESSAGES/django.po b/locale/eo_UY/LC_MESSAGES/django.po
index 47bd205ef..1a95d4766 100644
--- a/locale/eo_UY/LC_MESSAGES/django.po
+++ b/locale/eo_UY/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 19:32\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Esperanto\n"
"Language: eo\n"
@@ -1372,8 +1372,8 @@ msgstr "Eldonoj de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Eldonoj de «%(work_title)s» "
+msgid "Editions of %(work_title)s "
+msgstr "Eldonoj de %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,14 +2805,10 @@ msgstr "La CSV-a dosiero ne validas"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] ""
-msgstr[1] ""
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] "Aktuale vi rajtas importi %(display_size)s librojn ĉiun %(import_limit_reset)s tagon."
+msgstr[1] "Aktuale vi rajtas importi %(import_size_limit)s librojn ĉiujn %(import_limit_reset)s tagojn."
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/es_ES/LC_MESSAGES/django.mo b/locale/es_ES/LC_MESSAGES/django.mo
index 95c05e2cc..9ed73ceed 100644
Binary files a/locale/es_ES/LC_MESSAGES/django.mo and b/locale/es_ES/LC_MESSAGES/django.mo differ
diff --git a/locale/es_ES/LC_MESSAGES/django.po b/locale/es_ES/LC_MESSAGES/django.po
index 7738d0fa7..7f27a3e61 100644
--- a/locale/es_ES/LC_MESSAGES/django.po
+++ b/locale/es_ES/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 14:47\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-30 00:47\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Spanish\n"
"Language: es\n"
@@ -1035,7 +1035,7 @@ msgstr "Tus citas"
#: bookwyrm/templates/book/book.html:360
msgid "Subjects"
-msgstr "Sujetos"
+msgstr "Temas"
#: bookwyrm/templates/book/book.html:372
msgid "Places"
@@ -1372,8 +1372,8 @@ msgstr "Ediciones de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Ediciones de \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr "Ediciones de %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,18 +2805,10 @@ msgstr "No es un archivo CSV válido"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] "\n"
-" Actualmente, puedes importar %(display_size)s libros cada %(import_limit_reset)s días.\n"
-" "
-msgstr[1] "\n"
-" Actualmente, puedes importar %(import_size_limit)s libros cada %(import_limit_reset)s días.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] "Actualmente, puedes importar %(display_size)s libros cada %(import_limit_reset)s días."
+msgstr[1] "Actualmente, puedes importar %(import_size_limit)s libros cada %(import_limit_reset)s días."
#: bookwyrm/templates/import/import.html:27
#, python-format
@@ -6162,7 +6154,7 @@ msgstr "Apoya a %(site_name)s en GitHub ."
-msgstr "BookWyrm es software libre y de código abierto. Puedes contribuir o reportar problemas en GitHub ."
+msgstr "BookWyrm es software de código abierto. Puedes contribuir o reportar problemas en GitHub ."
#: bookwyrm/templates/snippets/form_rate_stars.html:20
#: bookwyrm/templates/snippets/stars.html:23
diff --git a/locale/eu_ES/LC_MESSAGES/django.mo b/locale/eu_ES/LC_MESSAGES/django.mo
index 572a0f9b2..cceaa551c 100644
Binary files a/locale/eu_ES/LC_MESSAGES/django.mo and b/locale/eu_ES/LC_MESSAGES/django.mo differ
diff --git a/locale/eu_ES/LC_MESSAGES/django.po b/locale/eu_ES/LC_MESSAGES/django.po
index 24ede78e9..fe0ec9634 100644
--- a/locale/eu_ES/LC_MESSAGES/django.po
+++ b/locale/eu_ES/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Basque\n"
"Language: eu\n"
@@ -1372,8 +1372,8 @@ msgstr "%(book_title)s(r)en edizioak"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "\"%(work_title)s\" -ren edizioak"
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr "CSV fitxategia ez da baliozkoa"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/fi_FI/LC_MESSAGES/django.mo b/locale/fi_FI/LC_MESSAGES/django.mo
index beacc8844..aef95bcc0 100644
Binary files a/locale/fi_FI/LC_MESSAGES/django.mo and b/locale/fi_FI/LC_MESSAGES/django.mo differ
diff --git a/locale/fi_FI/LC_MESSAGES/django.po b/locale/fi_FI/LC_MESSAGES/django.po
index b25e5c8e0..67bd955a7 100644
--- a/locale/fi_FI/LC_MESSAGES/django.po
+++ b/locale/fi_FI/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-29 23:37\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Finnish\n"
"Language: fi\n"
@@ -1372,8 +1372,8 @@ msgstr "Kirjan %(book_title)s laitokset"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Kirjan \"%(work_title)s\" laitokset"
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr "Epäkelpo CSV-tiedosto"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo
index fd48c948c..4cdcbf8ea 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 452c08205..1bd27f690 100644
--- a/locale/fr_FR/LC_MESSAGES/django.po
+++ b/locale/fr_FR/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-31 20:26\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: French\n"
"Language: fr\n"
@@ -310,47 +310,47 @@ msgstr "Commentaire"
#: bookwyrm/models/report.py:85
msgid "Resolved report"
-msgstr ""
+msgstr "Signalement résolu"
#: bookwyrm/models/report.py:86
msgid "Re-opened report"
-msgstr ""
+msgstr "Ouvrir le signalement de nouveau"
#: bookwyrm/models/report.py:87
msgid "Messaged reporter"
-msgstr ""
+msgstr "Rapporteur contacté"
#: bookwyrm/models/report.py:88
msgid "Messaged reported user"
-msgstr ""
+msgstr "Compte signalé contacté"
#: bookwyrm/models/report.py:89
msgid "Suspended user"
-msgstr ""
+msgstr "Compte suspendu"
#: bookwyrm/models/report.py:90
msgid "Un-suspended user"
-msgstr ""
+msgstr "Compte non‑suspendu"
#: bookwyrm/models/report.py:91
msgid "Changed user permission level"
-msgstr ""
+msgstr "Niveau des permissions utilisateur modifié"
#: bookwyrm/models/report.py:92
msgid "Deleted user account"
-msgstr ""
+msgstr "Compte supprimé"
#: bookwyrm/models/report.py:93
msgid "Blocked domain"
-msgstr ""
+msgstr "Domaine bloqué"
#: bookwyrm/models/report.py:94
msgid "Approved domain"
-msgstr ""
+msgstr "Domaine approuvé"
#: bookwyrm/models/report.py:95
msgid "Deleted item"
-msgstr ""
+msgstr "Item supprimé"
#: bookwyrm/models/user.py:32 bookwyrm/templates/book/book.html:307
msgid "Reviews"
@@ -378,7 +378,7 @@ msgstr "Accueil"
#: bookwyrm/settings.py:224
msgid "Books Timeline"
-msgstr "Actualité de mes livres"
+msgstr "Mon fil d’actualité littéraire"
#: bookwyrm/settings.py:224
#: bookwyrm/templates/guided_tour/user_profile.html:101
@@ -434,7 +434,7 @@ msgstr "Lietuvių (Lituanien)"
#: bookwyrm/settings.py:307
msgid "Nederlands (Dutch)"
-msgstr ""
+msgstr "Pays‑Bas (Néerlandais)"
#: bookwyrm/settings.py:308
msgid "Norsk (Norwegian)"
@@ -1076,11 +1076,11 @@ msgstr "ISBN :"
#: bookwyrm/templates/book/book_identifiers.html:12
#: bookwyrm/templates/book/book_identifiers.html:13
msgid "Copy ISBN"
-msgstr ""
+msgstr "Copier l’ISBN"
#: bookwyrm/templates/book/book_identifiers.html:16
msgid "Copied ISBN!"
-msgstr ""
+msgstr "ISBN copié !"
#: bookwyrm/templates/book/book_identifiers.html:23
#: bookwyrm/templates/book/edit/edit_book_form.html:352
@@ -1245,7 +1245,7 @@ msgstr "Titre :"
#: bookwyrm/templates/book/edit/edit_book_form.html:35
msgid "Sort Title:"
-msgstr ""
+msgstr "Titre de tri :"
#: bookwyrm/templates/book/edit/edit_book_form.html:44
msgid "Subtitle:"
@@ -1372,8 +1372,8 @@ msgstr "Éditions de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Éditions de « %(work_title)s » "
+msgid "Editions of %(work_title)s "
+msgstr "Éditions de %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2268,7 +2268,7 @@ msgstr "Responsable"
#: bookwyrm/templates/groups/user_groups.html:35
msgid "No groups found."
-msgstr ""
+msgstr "Aucun groupe trouvé."
#: bookwyrm/templates/guided_tour/book.html:10
msgid "This is home page of a book. Let's see what you can do while you're here!"
@@ -2805,19 +2805,15 @@ msgstr "Fichier CSV non valide"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] ""
-msgstr[1] ""
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] "Vous êtes actuellement autorisé à importer %(display_size)s livres tous les %(import_limit_reset)s jours."
+msgstr[1] "Vous avez le droit d’importer %(display_size)s livres chaque %(import_limit_reset)s jours actuellement."
#: bookwyrm/templates/import/import.html:27
#, python-format
msgid "You have %(display_left)s left."
-msgstr ""
+msgstr "Encore %(display_left)s."
#: bookwyrm/templates/import/import.html:34
#, python-format
@@ -3483,7 +3479,7 @@ msgstr "Sauvegardé"
#: bookwyrm/templates/lists/list_items.html:50
msgid "No lists found."
-msgstr ""
+msgstr "Aucune liste trouvée."
#: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:14
msgid "Your Lists"
@@ -4575,7 +4571,7 @@ msgstr "Queues"
#: bookwyrm/templates/settings/celery.html:26
msgid "Streams"
-msgstr ""
+msgstr "Flux"
#: bookwyrm/templates/settings/celery.html:32
msgid "Broadcasts"
@@ -4583,15 +4579,15 @@ msgstr "Diffusion"
#: bookwyrm/templates/settings/celery.html:38
msgid "Inbox"
-msgstr ""
+msgstr "Boîte de réception"
#: bookwyrm/templates/settings/celery.html:51
msgid "Import triggered"
-msgstr ""
+msgstr "Import déclenché"
#: bookwyrm/templates/settings/celery.html:57
msgid "Connectors"
-msgstr ""
+msgstr "Connecteurs"
#: bookwyrm/templates/settings/celery.html:64
#: bookwyrm/templates/settings/site.html:91
@@ -4600,7 +4596,7 @@ msgstr "Images"
#: bookwyrm/templates/settings/celery.html:70
msgid "Suggested Users"
-msgstr ""
+msgstr "Comptes suggérés"
#: bookwyrm/templates/settings/celery.html:83
#: bookwyrm/templates/settings/invites/manage_invite_requests.html:43
@@ -4610,7 +4606,7 @@ msgstr "Email"
#: bookwyrm/templates/settings/celery.html:89
msgid "Misc"
-msgstr ""
+msgstr "Divers"
#: bookwyrm/templates/settings/celery.html:96
msgid "Low priority"
@@ -5424,22 +5420,22 @@ msgstr "Liens signalés"
#: bookwyrm/templates/settings/reports/report.html:66
msgid "Moderation Activity"
-msgstr ""
+msgstr "Activité de la modération"
#: bookwyrm/templates/settings/reports/report.html:73
#, python-format
msgid "%(user)s opened this report"
-msgstr ""
+msgstr "%(user)s a ouvert ce signalement"
#: bookwyrm/templates/settings/reports/report.html:86
#, python-format
msgid "%(user)s commented on this report:"
-msgstr ""
+msgstr "%(user)s a commenté ce signalement :"
#: bookwyrm/templates/settings/reports/report.html:90
#, python-format
msgid "%(user)s took an action on this report:"
-msgstr ""
+msgstr "%(user)s a traité ce signalement :"
#: bookwyrm/templates/settings/reports/report_header.html:6
#, python-format
@@ -5463,7 +5459,7 @@ msgstr "Signalement #%(report_id)s : compte @%(username)s"
#: bookwyrm/templates/settings/reports/report_links_table.html:19
msgid "Approve domain"
-msgstr ""
+msgstr "Approuver le domaine"
#: bookwyrm/templates/settings/reports/report_links_table.html:26
msgid "Block domain"
@@ -6053,7 +6049,7 @@ msgstr "Commentaire :"
#: bookwyrm/templates/snippets/create_status/post_options_block.html:19
msgid "Update"
-msgstr ""
+msgstr "Mettre à jour"
#: bookwyrm/templates/snippets/create_status/post_options_block.html:21
msgid "Post"
@@ -6711,8 +6707,8 @@ msgstr "A rejoint ce serveur %(date)s"
#, python-format
msgid "%(display_count)s follower"
msgid_plural "%(display_count)s followers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%(display_count)s abonné⋅e"
+msgstr[1] "%(display_count)s abonné⋅es"
#: bookwyrm/templates/user/user_preview.html:31
#, python-format
diff --git a/locale/gl_ES/LC_MESSAGES/django.mo b/locale/gl_ES/LC_MESSAGES/django.mo
index 30542ace1..780a8def4 100644
Binary files a/locale/gl_ES/LC_MESSAGES/django.mo and b/locale/gl_ES/LC_MESSAGES/django.mo differ
diff --git a/locale/gl_ES/LC_MESSAGES/django.po b/locale/gl_ES/LC_MESSAGES/django.po
index 37edcfee9..904c15a63 100644
--- a/locale/gl_ES/LC_MESSAGES/django.po
+++ b/locale/gl_ES/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 04:25\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-20 13:05\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Galician\n"
"Language: gl\n"
@@ -497,7 +497,7 @@ msgstr "Acerca de"
#: bookwyrm/templates/get_started/layout.html:22
#, python-format
msgid "Welcome to %(site_name)s!"
-msgstr "Sexas ben vida a %(site_name)s!"
+msgstr "Recibe a benvida a %(site_name)s!"
#: bookwyrm/templates/about/about.html:25
#, python-format
@@ -1372,8 +1372,8 @@ msgstr "Edicións de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edicións de %(work_title)s "
+msgid "Editions of %(work_title)s "
+msgstr "Edicións de %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,18 +2805,10 @@ msgstr "Non é un ficheiro CSV válido"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] "\n"
-" Actualmente, tes permiso para importar %(display_size)s libros cada %(import_limit_reset)s día.\n"
-" "
-msgstr[1] "\n"
-" Actualmente, tes permiso para importar %(import_size_limit)s libros cada %(import_limit_reset)s días.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] "Actualmente podes importar %(display_size)s libros cada %(import_limit_reset)s día."
+msgstr[1] "Actualmente podes importar %(import_size_limit)s libros cada %(import_limit_reset)s días."
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/it_IT/LC_MESSAGES/django.mo b/locale/it_IT/LC_MESSAGES/django.mo
index 2114d45c5..958cdcbf3 100644
Binary files a/locale/it_IT/LC_MESSAGES/django.mo and b/locale/it_IT/LC_MESSAGES/django.mo differ
diff --git a/locale/it_IT/LC_MESSAGES/django.po b/locale/it_IT/LC_MESSAGES/django.po
index d0c4e2c69..379d826a6 100644
--- a/locale/it_IT/LC_MESSAGES/django.po
+++ b/locale/it_IT/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 09:30\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 19:32\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Italian\n"
"Language: it\n"
@@ -310,15 +310,15 @@ msgstr "Commenta"
#: bookwyrm/models/report.py:85
msgid "Resolved report"
-msgstr ""
+msgstr "Segnalazione risolta"
#: bookwyrm/models/report.py:86
msgid "Re-opened report"
-msgstr ""
+msgstr "Segnalazione riaperta"
#: bookwyrm/models/report.py:87
msgid "Messaged reporter"
-msgstr ""
+msgstr "Messaggio inviato al segnalatore"
#: bookwyrm/models/report.py:88
msgid "Messaged reported user"
@@ -326,11 +326,11 @@ msgstr ""
#: bookwyrm/models/report.py:89
msgid "Suspended user"
-msgstr ""
+msgstr "Utente sospeso"
#: bookwyrm/models/report.py:90
msgid "Un-suspended user"
-msgstr ""
+msgstr "Utente riattivato"
#: bookwyrm/models/report.py:91
msgid "Changed user permission level"
@@ -1372,8 +1372,8 @@ msgstr "Edizioni di %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edizioni di \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr "Edizioni di %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,14 +2805,10 @@ msgstr "Non è un file di csv valido"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
-msgstr[1] ""
+msgstr[1] "Al momento puoi importare %(import_size_limit)s libri ogni %(import_limit_reset)s giorni."
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/lt_LT/LC_MESSAGES/django.mo b/locale/lt_LT/LC_MESSAGES/django.mo
index 9f002fe1b..7f23c75a3 100644
Binary files a/locale/lt_LT/LC_MESSAGES/django.mo and b/locale/lt_LT/LC_MESSAGES/django.mo differ
diff --git a/locale/lt_LT/LC_MESSAGES/django.po b/locale/lt_LT/LC_MESSAGES/django.po
index c86bd8fc8..771492f85 100644
--- a/locale/lt_LT/LC_MESSAGES/django.po
+++ b/locale/lt_LT/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Lithuanian\n"
"Language: lt\n"
@@ -1384,8 +1384,8 @@ msgstr "Knygos %(book_title)s leidimai"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "\"%(work_title)s\" leidimai"
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2825,12 +2825,8 @@ msgstr "Netinkamas CSV failas"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
diff --git a/locale/nl_NL/LC_MESSAGES/django.mo b/locale/nl_NL/LC_MESSAGES/django.mo
index 4f0130fd2..088c596b1 100644
Binary files a/locale/nl_NL/LC_MESSAGES/django.mo and b/locale/nl_NL/LC_MESSAGES/django.mo differ
diff --git a/locale/nl_NL/LC_MESSAGES/django.po b/locale/nl_NL/LC_MESSAGES/django.po
index 5945b5257..0cb6c8ee5 100644
--- a/locale/nl_NL/LC_MESSAGES/django.po
+++ b/locale/nl_NL/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 08:16\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 19:32\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Dutch\n"
"Language: nl\n"
@@ -1372,8 +1372,8 @@ msgstr "Edities van %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edities van \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr "Edities van %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,16 +2805,10 @@ msgstr "Geen geldig CSV-bestand"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
-msgstr[0] "\n"
-"Momenteel mag je elke %(import_limit_reset)s dag %(display_size)s boeken importeren. "
-msgstr[1] "\n"
-"Momenteel mag je elke %(import_limit_reset)s dagen %(import_size_limit)s boeken importeren. "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
+msgstr[0] "Momenteel mag je %(display_size)s boek importeren elke %(import_limit_reset)s dagen."
+msgstr[1] "Momenteel mag je %(import_size_limit)s boeken importeren elke %(import_limit_reset)s dagen."
#: bookwyrm/templates/import/import.html:27
#, python-format
diff --git a/locale/no_NO/LC_MESSAGES/django.mo b/locale/no_NO/LC_MESSAGES/django.mo
index 66dfbb931..f2038692f 100644
Binary files a/locale/no_NO/LC_MESSAGES/django.mo and b/locale/no_NO/LC_MESSAGES/django.mo differ
diff --git a/locale/no_NO/LC_MESSAGES/django.po b/locale/no_NO/LC_MESSAGES/django.po
index 851887e7c..3c125d8aa 100644
--- a/locale/no_NO/LC_MESSAGES/django.po
+++ b/locale/no_NO/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-09 19:52\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Norwegian\n"
"Language: no\n"
@@ -314,31 +314,31 @@ msgstr ""
#: bookwyrm/models/report.py:86
msgid "Re-opened report"
-msgstr ""
+msgstr "Gjenåpnet rapport"
#: bookwyrm/models/report.py:87
msgid "Messaged reporter"
-msgstr ""
+msgstr "Melding sendt til rapportør"
#: bookwyrm/models/report.py:88
msgid "Messaged reported user"
-msgstr ""
+msgstr "Melding sendt til rapportert bruker"
#: bookwyrm/models/report.py:89
msgid "Suspended user"
-msgstr ""
+msgstr "Deaktivert bruker"
#: bookwyrm/models/report.py:90
msgid "Un-suspended user"
-msgstr ""
+msgstr "Reaktivert bruker"
#: bookwyrm/models/report.py:91
msgid "Changed user permission level"
-msgstr ""
+msgstr "Endret brukerens rettighetsnivå"
#: bookwyrm/models/report.py:92
msgid "Deleted user account"
-msgstr ""
+msgstr "Slettet brukerkonto"
#: bookwyrm/models/report.py:93
msgid "Blocked domain"
@@ -1372,8 +1372,8 @@ msgstr "Utgaver av %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Utgaver av \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr "Ikke en gyldig CSV-fil"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/pl_PL/LC_MESSAGES/django.mo b/locale/pl_PL/LC_MESSAGES/django.mo
index 7c12649d7..e7134182d 100644
Binary files a/locale/pl_PL/LC_MESSAGES/django.mo and b/locale/pl_PL/LC_MESSAGES/django.mo differ
diff --git a/locale/pl_PL/LC_MESSAGES/django.po b/locale/pl_PL/LC_MESSAGES/django.po
index 9544f3110..a5d366804 100644
--- a/locale/pl_PL/LC_MESSAGES/django.po
+++ b/locale/pl_PL/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-03 01:28\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Polish\n"
"Language: pl\n"
@@ -350,7 +350,7 @@ msgstr ""
#: bookwyrm/models/report.py:95
msgid "Deleted item"
-msgstr ""
+msgstr "Usunięty element"
#: bookwyrm/models/user.py:32 bookwyrm/templates/book/book.html:307
msgid "Reviews"
@@ -434,7 +434,7 @@ msgstr "Lietuvių (Litewski)"
#: bookwyrm/settings.py:307
msgid "Nederlands (Dutch)"
-msgstr ""
+msgstr "Holenderski"
#: bookwyrm/settings.py:308
msgid "Norsk (Norwegian)"
@@ -502,7 +502,7 @@ msgstr "Witaj na %(site_name)s!"
#: bookwyrm/templates/about/about.html:25
#, python-format
msgid "%(site_name)s is part of BookWyrm , a network of independent, self-directed communities for readers. While you can interact seamlessly with users anywhere in the BookWyrm network , this community is unique."
-msgstr ""
+msgstr "%(site_name)s jest częścią BookWyrm , sieci niezależnych, samostanowiących społeczności czytelników. Możesz beproblemowo wchodzić w interakcje z użytkownikami gdziekolwiek w sieci BookWyrm , ta społeczność jest wyjątkowa."
#: bookwyrm/templates/about/about.html:45
#, python-format
@@ -521,7 +521,7 @@ msgstr "%(title)s ma najbardziej podzielo
#: bookwyrm/templates/about/about.html:94
msgid "Track your reading, talk about books, write reviews, and discover what to read next. Always ad-free, anti-corporate, and community-oriented, BookWyrm is human-scale software, designed to stay small and personal. If you have feature requests, bug reports, or grand dreams, reach out and make yourself heard."
-msgstr ""
+msgstr "Śledź swój postęp czytelniczy, rozmawiaj o książkach, pisz opinie i odkrywaj co czytać następne. Na zawsze bez reklam, antykorporacyjne i skierowane w stronę społeczności, BookWyrm jest programem dla ludzi, stworzonym, by pozostać małym i personalnym. Jeśli masz pomysł, zauważył_ś błąd, albo masz wielkie marzenie, złoś się i pozwól się wysłuchać."
#: bookwyrm/templates/about/about.html:105
msgid "Meet your admins"
@@ -672,7 +672,7 @@ msgstr "Przekłada się to na średnio %(pages)s stron na książkę."
#, python-format
msgid "(No page data was available for %(no_page_number)s book)"
msgid_plural "(No page data was available for %(no_page_number)s books)"
-msgstr[0] ""
+msgstr[0] "(Nie mamy informacji o liczbie stron dla książki %(no_page_number)s)"
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
@@ -778,7 +778,7 @@ msgstr "Zobacz wpis ISNI"
#: bookwyrm/templates/author/author.html:95
#: bookwyrm/templates/book/book.html:173
msgid "View on ISFDB"
-msgstr ""
+msgstr "Zobacz na ISFDB"
#: bookwyrm/templates/author/author.html:100
#: bookwyrm/templates/author/sync_modal.html:5
@@ -1116,7 +1116,7 @@ msgstr ""
#: bookwyrm/templates/book/book_identifiers.html:51
msgid "Goodreads:"
-msgstr ""
+msgstr "Goodreads:"
#: bookwyrm/templates/book/cover_add_modal.html:5
msgid "Add cover"
@@ -1257,7 +1257,7 @@ msgstr "Tytuł:"
#: bookwyrm/templates/book/edit/edit_book_form.html:35
msgid "Sort Title:"
-msgstr ""
+msgstr "Sortuj Według Tytułu:"
#: bookwyrm/templates/book/edit/edit_book_form.html:44
msgid "Subtitle:"
@@ -1384,8 +1384,8 @@ msgstr "Edycje %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edycje \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr "Edycje %(work_title)s "
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -1567,7 +1567,7 @@ msgstr ""
#: bookwyrm/templates/book/series.html:27
#, python-format
msgid "Book %(series_number)s"
-msgstr ""
+msgstr "Książka%(series_number)s"
#: bookwyrm/templates/book/series.html:27
msgid "Unsorted Book"
@@ -2825,12 +2825,8 @@ msgstr "To nie jest prawidłowy plik CSV"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
diff --git a/locale/pt_BR/LC_MESSAGES/django.mo b/locale/pt_BR/LC_MESSAGES/django.mo
index 05c4cbd8c..42da17a08 100644
Binary files a/locale/pt_BR/LC_MESSAGES/django.mo and b/locale/pt_BR/LC_MESSAGES/django.mo differ
diff --git a/locale/pt_BR/LC_MESSAGES/django.po b/locale/pt_BR/LC_MESSAGES/django.po
index c11dd5830..495ea43b3 100644
--- a/locale/pt_BR/LC_MESSAGES/django.po
+++ b/locale/pt_BR/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 18:50\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt\n"
@@ -1372,8 +1372,8 @@ msgstr "Edições de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edições de \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr ""
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/pt_PT/LC_MESSAGES/django.mo b/locale/pt_PT/LC_MESSAGES/django.mo
index 1ca5e1dd7..4e2f18bcb 100644
Binary files a/locale/pt_PT/LC_MESSAGES/django.mo and b/locale/pt_PT/LC_MESSAGES/django.mo differ
diff --git a/locale/pt_PT/LC_MESSAGES/django.po b/locale/pt_PT/LC_MESSAGES/django.po
index 807fade98..5788aff29 100644
--- a/locale/pt_PT/LC_MESSAGES/django.po
+++ b/locale/pt_PT/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Portuguese\n"
"Language: pt\n"
@@ -1372,8 +1372,8 @@ msgstr "Edições de %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Edições de \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr "Não é um ficheiro CSV válido"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/ro_RO/LC_MESSAGES/django.mo b/locale/ro_RO/LC_MESSAGES/django.mo
index 85a193ba8..7aa5899d1 100644
Binary files a/locale/ro_RO/LC_MESSAGES/django.mo and b/locale/ro_RO/LC_MESSAGES/django.mo differ
diff --git a/locale/ro_RO/LC_MESSAGES/django.po b/locale/ro_RO/LC_MESSAGES/django.po
index 5f1068e8b..54e13162c 100644
--- a/locale/ro_RO/LC_MESSAGES/django.po
+++ b/locale/ro_RO/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Romanian\n"
"Language: ro\n"
@@ -1378,8 +1378,8 @@ msgstr "Ediții ale %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Ediții ale %(work_title)s "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2815,12 +2815,8 @@ msgstr ""
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
diff --git a/locale/sv_SE/LC_MESSAGES/django.mo b/locale/sv_SE/LC_MESSAGES/django.mo
index 890f3304b..0086e5259 100644
Binary files a/locale/sv_SE/LC_MESSAGES/django.mo and b/locale/sv_SE/LC_MESSAGES/django.mo differ
diff --git a/locale/sv_SE/LC_MESSAGES/django.po b/locale/sv_SE/LC_MESSAGES/django.po
index 7246dbc19..78106ff7a 100644
--- a/locale/sv_SE/LC_MESSAGES/django.po
+++ b/locale/sv_SE/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 09:30\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Swedish\n"
"Language: sv\n"
@@ -1372,8 +1372,8 @@ msgstr "Utgåvor av %(book_title)s"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "Utgåvor av \"%(work_title)s\" "
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2805,12 +2805,8 @@ msgstr "Inte en giltig CSV-fil"
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
msgstr[1] ""
diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po
index a3c31e913..77591afa9 100644
--- a/locale/zh_Hans/LC_MESSAGES/django.po
+++ b/locale/zh_Hans/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-02 18:13\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Chinese Simplified\n"
"Language: zh\n"
@@ -1366,8 +1366,8 @@ msgstr "%(book_title)s 的各版本"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "《%(work_title)s》 的各版本"
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2795,12 +2795,8 @@ msgstr ""
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
#: bookwyrm/templates/import/import.html:27
diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po
index a95eebec1..c6f7dc28b 100644
--- a/locale/zh_Hant/LC_MESSAGES/django.po
+++ b/locale/zh_Hant/LC_MESSAGES/django.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: bookwyrm\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-27 01:11+0000\n"
-"PO-Revision-Date: 2023-09-28 00:08\n"
+"POT-Creation-Date: 2023-10-02 16:40+0000\n"
+"PO-Revision-Date: 2023-10-29 07:42\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: Chinese Traditional\n"
"Language: zh\n"
@@ -173,7 +173,7 @@ msgstr ""
#: bookwyrm/models/book.py:283
msgid "Audiobook"
-msgstr ""
+msgstr "有聲書"
#: bookwyrm/models/book.py:284
msgid "eBook"
@@ -181,15 +181,15 @@ msgstr "電子書"
#: bookwyrm/models/book.py:285
msgid "Graphic novel"
-msgstr ""
+msgstr "圖像小說"
#: bookwyrm/models/book.py:286
msgid "Hardcover"
-msgstr ""
+msgstr "精裝書"
#: bookwyrm/models/book.py:287
msgid "Paperback"
-msgstr ""
+msgstr "平裝書"
#: bookwyrm/models/federated_server.py:11
#: bookwyrm/templates/settings/federation/edit_instance.html:55
@@ -267,15 +267,15 @@ msgstr "活躍"
#: bookwyrm/models/import_job.py:49 bookwyrm/templates/import/import.html:172
msgid "Complete"
-msgstr ""
+msgstr "已完成"
#: bookwyrm/models/import_job.py:50
msgid "Stopped"
-msgstr ""
+msgstr "已停止"
#: bookwyrm/models/import_job.py:83 bookwyrm/models/import_job.py:91
msgid "Import stopped"
-msgstr ""
+msgstr "匯入已停止"
#: bookwyrm/models/import_job.py:363 bookwyrm/models/import_job.py:388
msgid "Error loading book"
@@ -287,20 +287,20 @@ msgstr ""
#: bookwyrm/models/link.py:51
msgid "Free"
-msgstr ""
+msgstr "免費"
#: bookwyrm/models/link.py:52
msgid "Purchasable"
-msgstr ""
+msgstr "可購買"
#: bookwyrm/models/link.py:53
msgid "Available for loan"
-msgstr ""
+msgstr "可借閱"
#: bookwyrm/models/link.py:70
#: bookwyrm/templates/settings/link_domains/link_domains.html:23
msgid "Approved"
-msgstr ""
+msgstr "已核准"
#: bookwyrm/models/report.py:84
#: bookwyrm/templates/settings/reports/report.html:115
@@ -310,11 +310,11 @@ msgstr "評論"
#: bookwyrm/models/report.py:85
msgid "Resolved report"
-msgstr ""
+msgstr "已處理的舉報"
#: bookwyrm/models/report.py:86
msgid "Re-opened report"
-msgstr ""
+msgstr "已重新打開的舉報"
#: bookwyrm/models/report.py:87
msgid "Messaged reporter"
@@ -358,15 +358,15 @@ msgstr "書評"
#: bookwyrm/models/user.py:33
msgid "Comments"
-msgstr ""
+msgstr "評論"
#: bookwyrm/models/user.py:34
msgid "Quotations"
-msgstr ""
+msgstr "引用"
#: bookwyrm/models/user.py:35
msgid "Everything else"
-msgstr ""
+msgstr "所有其他內容"
#: bookwyrm/settings.py:223
msgid "Home Timeline"
@@ -378,7 +378,7 @@ msgstr "主頁"
#: bookwyrm/settings.py:224
msgid "Books Timeline"
-msgstr ""
+msgstr "書目時間線"
#: bookwyrm/settings.py:224
#: bookwyrm/templates/guided_tour/user_profile.html:101
@@ -394,7 +394,7 @@ msgstr "English(英語)"
#: bookwyrm/settings.py:297
msgid "Català (Catalan)"
-msgstr ""
+msgstr "Català (加泰羅尼亞語)"
#: bookwyrm/settings.py:298
msgid "Deutsch (German)"
@@ -402,7 +402,7 @@ msgstr "Deutsch(德語)"
#: bookwyrm/settings.py:299
msgid "Esperanto (Esperanto)"
-msgstr ""
+msgstr "Esperanto (世界語)"
#: bookwyrm/settings.py:300
msgid "Español (Spanish)"
@@ -410,19 +410,19 @@ msgstr "Español(西班牙語)"
#: bookwyrm/settings.py:301
msgid "Euskara (Basque)"
-msgstr ""
+msgstr "Euskara (巴斯克語)"
#: bookwyrm/settings.py:302
msgid "Galego (Galician)"
-msgstr ""
+msgstr "Galego (加利西亞語)"
#: bookwyrm/settings.py:303
msgid "Italiano (Italian)"
-msgstr ""
+msgstr "Italiano (意大利語)"
#: bookwyrm/settings.py:304
msgid "Suomi (Finnish)"
-msgstr ""
+msgstr "Suomi (芬蘭語)"
#: bookwyrm/settings.py:305
msgid "Français (French)"
@@ -430,35 +430,35 @@ msgstr "Français(法語)"
#: bookwyrm/settings.py:306
msgid "Lietuvių (Lithuanian)"
-msgstr ""
+msgstr "Lietuvių (立陶宛語)"
#: bookwyrm/settings.py:307
msgid "Nederlands (Dutch)"
-msgstr ""
+msgstr "Nederlands (荷蘭語)"
#: bookwyrm/settings.py:308
msgid "Norsk (Norwegian)"
-msgstr ""
+msgstr "Norsk (挪威語)"
#: bookwyrm/settings.py:309
msgid "Polski (Polish)"
-msgstr ""
+msgstr "Polski (波蘭語)"
#: bookwyrm/settings.py:310
msgid "Português do Brasil (Brazilian Portuguese)"
-msgstr ""
+msgstr "Português do Brasil (巴西葡萄牙語)"
#: bookwyrm/settings.py:311
msgid "Português Europeu (European Portuguese)"
-msgstr ""
+msgstr "Português Europeu (歐洲葡萄牙語)"
#: bookwyrm/settings.py:312
msgid "Română (Romanian)"
-msgstr ""
+msgstr "Română (羅馬尼亞語)"
#: bookwyrm/settings.py:313
msgid "Svenska (Swedish)"
-msgstr ""
+msgstr "Svenska (瑞典語)"
#: bookwyrm/settings.py:314
msgid "简体中文 (Simplified Chinese)"
@@ -491,7 +491,7 @@ msgstr "某些東西出錯了!抱歉。"
#: bookwyrm/templates/about/about.html:9
#: bookwyrm/templates/about/layout.html:35
msgid "About"
-msgstr ""
+msgstr "關於"
#: bookwyrm/templates/about/about.html:21
#: bookwyrm/templates/get_started/layout.html:22
@@ -502,12 +502,12 @@ msgstr "歡迎來到 %(site_name)s!"
#: bookwyrm/templates/about/about.html:25
#, python-format
msgid "%(site_name)s is part of BookWyrm , a network of independent, self-directed communities for readers. While you can interact seamlessly with users anywhere in the BookWyrm network , this community is unique."
-msgstr ""
+msgstr "%(site_name)s 是 BookWyrm 的一部分,這是一個為讀者建立的獨立、自我導向的社區網絡。雖然您可以在 BookWyrm 網絡 中任何地方的用戶無縫互動,但這個社區是獨一無二的。"
#: bookwyrm/templates/about/about.html:45
#, python-format
msgid "%(title)s is %(site_name)s's most beloved book, with an average rating of %(rating)s out of 5."
-msgstr ""
+msgstr "%(title)s 是 %(site_name)s 最受歡迎的書,平均得分為 %(rating)s(滿分五分)。"
#: bookwyrm/templates/about/about.html:64
#, python-format
@@ -703,13 +703,13 @@ msgstr[0] ""
#: bookwyrm/templates/annual_summary/layout.html:211
msgid "Way to go!"
-msgstr ""
+msgstr "還不錯!"
#: bookwyrm/templates/annual_summary/layout.html:226
#, python-format
msgid "%(display_name)s left %(ratings_total)s rating, their average rating is %(rating_average)s"
msgid_plural "%(display_name)s left %(ratings_total)s ratings, their average rating is %(rating_average)s"
-msgstr[0] ""
+msgstr[0] "%(display_name)s 留下了 %(ratings_total)s 條評分, 他的平均評分是 %(rating_average)s"
#: bookwyrm/templates/annual_summary/layout.html:240
msgid "Their best rated review"
@@ -732,7 +732,7 @@ msgstr "編輯作者"
#: bookwyrm/templates/author/author.html:36
msgid "Author details"
-msgstr ""
+msgstr "作者詳情"
#: bookwyrm/templates/author/author.html:40
#: bookwyrm/templates/author/edit_author.html:42
@@ -749,7 +749,7 @@ msgstr "逝世:"
#: bookwyrm/templates/author/author.html:66
msgid "External links"
-msgstr ""
+msgstr "外部連結"
#: bookwyrm/templates/author/author.html:71
msgid "Wikipedia"
@@ -757,23 +757,23 @@ msgstr "維基百科"
#: bookwyrm/templates/author/author.html:79
msgid "Website"
-msgstr ""
+msgstr "網站"
#: bookwyrm/templates/author/author.html:87
msgid "View ISNI record"
-msgstr ""
+msgstr "查看 ISNI 記錄"
#: bookwyrm/templates/author/author.html:95
#: bookwyrm/templates/book/book.html:173
msgid "View on ISFDB"
-msgstr ""
+msgstr "在 ISFDB 查看"
#: bookwyrm/templates/author/author.html:100
#: bookwyrm/templates/author/sync_modal.html:5
#: bookwyrm/templates/book/book.html:140
#: bookwyrm/templates/book/sync_modal.html:5
msgid "Load data"
-msgstr ""
+msgstr "載入資料"
#: bookwyrm/templates/author/author.html:104
#: bookwyrm/templates/book/book.html:144
@@ -787,15 +787,15 @@ msgstr "在 Inventaire 檢視"
#: bookwyrm/templates/author/author.html:135
msgid "View on LibraryThing"
-msgstr ""
+msgstr "在 LibraryThing 查看"
#: bookwyrm/templates/author/author.html:143
msgid "View on Goodreads"
-msgstr ""
+msgstr "在 Goodreads 查看"
#: bookwyrm/templates/author/author.html:151
msgid "View ISFDB entry"
-msgstr ""
+msgstr "查看 ISFDB 條目"
#: bookwyrm/templates/author/author.html:166
#, python-format
@@ -849,7 +849,7 @@ msgstr "維基百科連結:"
#: bookwyrm/templates/author/edit_author.html:60
msgid "Website:"
-msgstr ""
+msgstr "網站:"
#: bookwyrm/templates/author/edit_author.html:65
msgid "Birth date:"
@@ -883,11 +883,11 @@ msgstr "Goodreads key:"
#: bookwyrm/templates/author/edit_author.html:109
msgid "ISFDB:"
-msgstr ""
+msgstr "ISFDB:"
#: bookwyrm/templates/author/edit_author.html:116
msgid "ISNI:"
-msgstr ""
+msgstr "ISNI:"
#: bookwyrm/templates/author/edit_author.html:126
#: bookwyrm/templates/book/book.html:220
@@ -953,7 +953,7 @@ msgstr "確認"
#: bookwyrm/templates/book/book.html:20
msgid "Unable to connect to remote source."
-msgstr ""
+msgstr "無法連接到遠程數據源。"
#: bookwyrm/templates/book/book.html:71 bookwyrm/templates/book/book.html:72
msgid "Edit Book"
@@ -961,7 +961,7 @@ msgstr "編輯書目"
#: bookwyrm/templates/book/book.html:97 bookwyrm/templates/book/book.html:100
msgid "Click to add cover"
-msgstr ""
+msgstr "點擊添加封面"
#: bookwyrm/templates/book/book.html:106
msgid "Failed to load cover"
@@ -969,7 +969,7 @@ msgstr "載入封面失敗"
#: bookwyrm/templates/book/book.html:117
msgid "Click to enlarge"
-msgstr ""
+msgstr "點擊放大"
#: bookwyrm/templates/book/book.html:196
#, python-format
@@ -991,7 +991,7 @@ msgstr "描述:"
#, python-format
msgid "%(count)s edition"
msgid_plural "%(count)s editions"
-msgstr[0] ""
+msgstr[0] "%(count)s 版次"
#: bookwyrm/templates/book/book.html:246
msgid "You have shelved this edition in:"
@@ -1070,11 +1070,11 @@ msgstr "ISBN:"
#: bookwyrm/templates/book/book_identifiers.html:12
#: bookwyrm/templates/book/book_identifiers.html:13
msgid "Copy ISBN"
-msgstr ""
+msgstr "複製ISBN"
#: bookwyrm/templates/book/book_identifiers.html:16
msgid "Copied ISBN!"
-msgstr ""
+msgstr "已複製ISBN!"
#: bookwyrm/templates/book/book_identifiers.html:23
#: bookwyrm/templates/book/edit/edit_book_form.html:352
@@ -1089,16 +1089,16 @@ msgstr "ASIN:"
#: bookwyrm/templates/book/book_identifiers.html:37
#: bookwyrm/templates/book/edit/edit_book_form.html:370
msgid "Audible ASIN:"
-msgstr ""
+msgstr "Audible ASIN:"
#: bookwyrm/templates/book/book_identifiers.html:44
#: bookwyrm/templates/book/edit/edit_book_form.html:379
msgid "ISFDB ID:"
-msgstr ""
+msgstr "ISFDB ID:"
#: bookwyrm/templates/book/book_identifiers.html:51
msgid "Goodreads:"
-msgstr ""
+msgstr "Goodreads:"
#: bookwyrm/templates/book/cover_add_modal.html:5
msgid "Add cover"
@@ -1116,7 +1116,7 @@ msgstr "從網址載入封面:"
#: bookwyrm/templates/book/cover_show_modal.html:6
msgid "Book cover preview"
-msgstr ""
+msgstr "書籍封面預覽"
#: bookwyrm/templates/book/cover_show_modal.html:11
#: bookwyrm/templates/components/inline_form.html:8
@@ -1310,16 +1310,16 @@ msgstr "新增作者:"
#: bookwyrm/templates/book/edit/edit_book_form.html:211
#: bookwyrm/templates/book/edit/edit_book_form.html:214
msgid "Add Author"
-msgstr ""
+msgstr "新增作者"
#: bookwyrm/templates/book/edit/edit_book_form.html:212
#: bookwyrm/templates/book/edit/edit_book_form.html:215
msgid "Jane Doe"
-msgstr ""
+msgstr "陳大文"
#: bookwyrm/templates/book/edit/edit_book_form.html:221
msgid "Add Another Author"
-msgstr ""
+msgstr "新增其他作者"
#: bookwyrm/templates/book/edit/edit_book_form.html:231
#: bookwyrm/templates/shelf/shelf.html:147
@@ -1337,7 +1337,7 @@ msgstr "格式:"
#: bookwyrm/templates/book/edit/edit_book_form.html:280
msgid "Format details:"
-msgstr ""
+msgstr "裝訂詳情:"
#: bookwyrm/templates/book/edit/edit_book_form.html:291
msgid "Pages:"
@@ -1366,8 +1366,8 @@ msgstr "%(book_title)s 的各版本"
#: bookwyrm/templates/book/editions/editions.html:8
#, python-format
-msgid "Editions of \"%(work_title)s\" "
-msgstr "\"%(work_title)s\" 的各版本"
+msgid "Editions of %(work_title)s "
+msgstr ""
#: bookwyrm/templates/book/editions/editions.html:55
msgid "Can't find the edition you're looking for?"
@@ -2795,12 +2795,8 @@ msgstr ""
#: bookwyrm/templates/import/import.html:21
#, python-format
-msgid "\n"
-" Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day.\n"
-" "
-msgid_plural "\n"
-" Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days.\n"
-" "
+msgid "Currently, you are allowed to import %(display_size)s books every %(import_limit_reset)s day."
+msgid_plural "Currently, you are allowed to import %(import_size_limit)s books every %(import_limit_reset)s days."
msgstr[0] ""
#: bookwyrm/templates/import/import.html:27
diff --git a/requirements.txt b/requirements.txt
index cda7b1967..027835276 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@ aiohttp==3.8.5
bleach==5.0.1
celery==5.2.7
colorthief==0.2.1
-Django==3.2.20
+Django==3.2.23
django-celery-beat==2.4.0
bw-file-resubmit==0.6.0rc2
django-compressor==4.3.1