Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2021-08-07 08:34:05 -07:00
commit c105490178
31 changed files with 1185 additions and 191 deletions

View file

@ -36,6 +36,7 @@ jobs:
env:
SECRET_KEY: beepbeep
DEBUG: false
USE_HTTPS: true
DOMAIN: your.domain.here
BOOKWYRM_DATABASE_BACKEND: postgres
MEDIA_ROOT: images/

View file

@ -23,6 +23,14 @@ def email_data():
}
def email_confirmation_email(user):
"""newly registered users confirm email address"""
data = email_data()
data["confirmation_code"] = user.confirmation_code
data["confirmation_link"] = user.confirmation_link
send_email.delay(user.email, *format_email("confirm", data))
def invite_email(invite_request):
"""send out an invite code"""
data = email_data()

View file

@ -0,0 +1,56 @@
# Generated by Django 3.2.4 on 2021-08-06 23:24
import bookwyrm.models.base_model
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0081_alter_user_last_active_date"),
]
operations = [
migrations.AddField(
model_name="sitesettings",
name="require_confirm_email",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="user",
name="confirmation_code",
field=models.CharField(
default=bookwyrm.models.base_model.new_access_code, max_length=32
),
),
migrations.AlterField(
model_name="connector",
name="deactivation_reason",
field=models.CharField(
blank=True,
choices=[
("pending", "Pending"),
("self_deletion", "Self Deletion"),
("moderator_deletion", "Moderator Deletion"),
("domain_block", "Domain Block"),
],
max_length=255,
null=True,
),
),
migrations.AlterField(
model_name="user",
name="deactivation_reason",
field=models.CharField(
blank=True,
choices=[
("pending", "Pending"),
("self_deletion", "Self Deletion"),
("moderator_deletion", "Moderator Deletion"),
("domain_block", "Domain Block"),
],
max_length=255,
null=True,
),
),
]

View file

@ -1,4 +1,6 @@
""" base model with default fields """
import base64
from Crypto import Random
from django.db import models
from django.dispatch import receiver
@ -9,6 +11,7 @@ from .fields import RemoteIdField
DeactivationReason = models.TextChoices(
"DeactivationReason",
[
"pending",
"self_deletion",
"moderator_deletion",
"domain_block",
@ -16,6 +19,11 @@ DeactivationReason = models.TextChoices(
)
def new_access_code():
"""the identifier for a user invite"""
return base64.b32encode(Random.get_random_bytes(5)).decode("ascii")
class BookWyrmModel(models.Model):
"""shared fields"""

View file

@ -1,8 +1,6 @@
""" the particulars for this instance of BookWyrm """
import base64
import datetime
from Crypto import Random
from django.db import models, IntegrityError
from django.dispatch import receiver
from django.utils import timezone
@ -10,7 +8,7 @@ from model_utils import FieldTracker
from bookwyrm.preview_images import generate_site_preview_image_task
from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES
from .base_model import BookWyrmModel
from .base_model import BookWyrmModel, new_access_code
from .user import User
@ -33,6 +31,7 @@ class SiteSettings(models.Model):
# registration
allow_registration = models.BooleanField(default=True)
allow_invite_requests = models.BooleanField(default=True)
require_confirm_email = models.BooleanField(default=True)
# images
logo = models.ImageField(upload_to="logos/", null=True, blank=True)
@ -61,11 +60,6 @@ class SiteSettings(models.Model):
return default_settings
def new_access_code():
"""the identifier for a user invite"""
return base64.b32encode(Random.get_random_bytes(5)).decode("ascii")
class SiteInvite(models.Model):
"""gives someone access to create an account on the instance"""

View file

@ -17,16 +17,22 @@ from bookwyrm.connectors import get_data, ConnectorException
from bookwyrm.models.shelf import Shelf
from bookwyrm.models.status import Status, Review
from bookwyrm.preview_images import generate_user_preview_image_task
from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES
from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, USE_HTTPS
from bookwyrm.signatures import create_key_pair
from bookwyrm.tasks import app
from bookwyrm.utils import regex
from .activitypub_mixin import OrderedCollectionPageMixin, ActivitypubMixin
from .base_model import BookWyrmModel, DeactivationReason
from .base_model import BookWyrmModel, DeactivationReason, new_access_code
from .federated_server import FederatedServer
from . import fields, Review
def site_link():
"""helper for generating links to the site"""
protocol = "https" if USE_HTTPS else "http"
return f"{protocol}://{DOMAIN}"
class User(OrderedCollectionPageMixin, AbstractUser):
"""a user who wants to read books"""
@ -123,11 +129,18 @@ class User(OrderedCollectionPageMixin, AbstractUser):
deactivation_reason = models.CharField(
max_length=255, choices=DeactivationReason.choices, null=True, blank=True
)
confirmation_code = models.CharField(max_length=32, default=new_access_code)
name_field = "username"
property_fields = [("following_link", "following")]
field_tracker = FieldTracker(fields=["name", "avatar"])
@property
def confirmation_link(self):
"""helper for generating confirmation links"""
link = site_link()
return f"{link}/confirm-email/{self.confirmation_code}"
@property
def following_link(self):
"""just how to find out the following info"""
@ -207,7 +220,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
self.following.order_by("-updated_date").all(),
remote_id=remote_id,
id_only=True,
**kwargs
**kwargs,
)
def to_followers_activity(self, **kwargs):
@ -217,7 +230,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
self.followers.order_by("-updated_date").all(),
remote_id=remote_id,
id_only=True,
**kwargs
**kwargs,
)
def to_activity(self, **kwargs):
@ -259,9 +272,9 @@ class User(OrderedCollectionPageMixin, AbstractUser):
return
# populate fields for local users
self.remote_id = "https://%s/user/%s" % (DOMAIN, self.localname)
self.remote_id = "%s/user/%s" % (site_link(), self.localname)
self.inbox = "%s/inbox" % self.remote_id
self.shared_inbox = "https://%s/inbox" % DOMAIN
self.shared_inbox = "%s/inbox" % site_link()
self.outbox = "%s/outbox" % self.remote_id
# an id needs to be set before we can proceed with related models

View file

@ -0,0 +1,44 @@
{% extends "layout.html" %}
{% load i18n %}
{% block title %}{% trans "Confirm email" %}{% endblock %}
{% block content %}
<h1 class="title">{% trans "Confirm your email address" %}</h1>
<div class="columns">
<div class="column">
<div class="block content">
<section class="block">
<p>{% trans "A confirmation code has been sent to the email address you used to register your account." %}</p>
{% if not valid %}
<p class="notification is-warning">{% trans "Sorry! We couldn't find that code." %}</p>
{% endif %}
<form name="confirm" method="post" action="{% url 'confirm-email' %}">
{% csrf_token %}
<label class="label" for="confirmation_code">{% trans "Confirmation code:" %}</label>
<div class="field has-addons">
<div class="control">
<input class="input" type="text" name="code" id="confirmation_code" required>
</div>
<div class="control">
<button class="button is-link" type="submit">{% trans "Submit" %}</button>
</div>
</div>
</form>
</section>
<section class="block">
{% trans "Can't find your code?" as button_text %}
{% include "snippets/toggle/open_button.html" with text=button_text controls_text="resend-form" focus="resend-form-header" %}
{% include "confirm_email/resend_form.html" with controls_text="resend-form" %}
</section>
</div>
</div>
<div class="column">
<div class="box">
{% include 'snippets/about.html' %}
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "components/inline_form.html" %}
{% load i18n %}
{% block header %}
{% trans "Resend confirmation link" %}
{% endblock %}
{% block form %}
<form name="resend" method="post" action="{% url 'resend-link' %}">
{% csrf_token %}
<div class="field">
<label class="label" for="email">{% trans "Email address:" %}</label>
<div class="control">
<input type="text" name="email" class="input" required id="email">
</div>
</div>
<div class="control">
<button class="button is-link">{% trans "Resend link" %}</button>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends 'email/html_layout.html' %}
{% load i18n %}
{% block content %}
<p>
{% blocktrans trimmed %}
One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below:
{% endblocktrans %}
</p>
{% trans "Confirm Email" as text %}
{% include 'email/snippets/action.html' with path=confirmation_link text=text %}
<p>
{% blocktrans trimmed %}
Or enter the code "<code>{{ confirmation_code }}</code>" at login.
{% endblocktrans %}
</p>
{% endblock %}

View file

@ -0,0 +1,4 @@
{% load i18n %}
{% blocktrans trimmed %}
Please confirm your email
{% endblocktrans %}

View file

@ -0,0 +1,14 @@
{% extends 'email/text_layout.html' %}
{% load i18n %}
{% block content %}
{% blocktrans trimmed %}
One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below:
{% endblocktrans %}
{{ confirmation_link }}
{% blocktrans trimmed %}
Or enter the code "{{ confirmation_code }}" at login.
{% endblocktrans %}
{% endblock %}

View file

@ -11,8 +11,13 @@
{% if login_form.non_field_errors %}
<p class="notification is-danger">{{ login_form.non_field_errors }}</p>
{% endif %}
{% if show_confirmed_email %}
<p class="notification is-success">{% trans "Success! Email address confirmed." %}</p>
{% endif %}
<form name="login" method="post" action="/login">
{% csrf_token %}
{% if show_confirmed_email %}<input type="hidden" name="first_login" value="true">{% endif %}
<div class="field">
<label class="label" for="id_localname">{% trans "Username:" %}</label>
<div class="control">

View file

@ -91,6 +91,13 @@
{% trans "Allow invite requests" %}
</label>
</div>
<div class="field">
<label class="label mb-0" for="id_allow_invite_requests">
{{ site_form.require_confirm_email }}
{% trans "Require users to confirm email address" %}
</label>
<p class="help">{% trans "(Recommended if registration is open)" %}</p>
</div>
<div class="field">
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
{{ site_form.registration_closed_text }}

View file

@ -12,7 +12,7 @@
<div class="field">
<label class="label" for="id_email_register">{% trans "Email address:" %}</label>
<div class="control">
<input type="email" name="email" maxlength="254" class="input" id="id_email_register" value="{% if register_form.email.value %}{{ register_form.email.value }}{% endif %}">
<input type="email" name="email" maxlength="254" class="input" id="id_email_register" value="{% if register_form.email.value %}{{ register_form.email.value }}{% endif %}" required>
{% for error in register_form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}

View file

@ -12,7 +12,7 @@ register = template.Library()
def get_rating(book, user):
"""get the overall rating of a book"""
queryset = views.helpers.privacy_filter(
user, models.Review.objects.filter(book=book)
user, models.Review.objects.filter(book__in=book.parent_work.editions.all())
)
return queryset.aggregate(Avg("rating"))["rating__avg"]

View file

@ -175,3 +175,10 @@ class TemplateTags(TestCase):
result = bookwyrm_tags.related_status(notification)
self.assertIsInstance(result, models.Status)
def test_get_next_shelf(self, *_):
"""self progress helper"""
self.assertEqual(bookwyrm_tags.get_next_shelf("to-read"), "reading")
self.assertEqual(bookwyrm_tags.get_next_shelf("reading"), "read")
self.assertEqual(bookwyrm_tags.get_next_shelf("read"), "read")
self.assertEqual(bookwyrm_tags.get_next_shelf("blooooga"), "to-read")

View file

@ -8,7 +8,7 @@ from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm import forms, models, views
from bookwyrm.settings import DOMAIN
@ -22,7 +22,7 @@ class AuthenticationViews(TestCase):
self.factory = RequestFactory()
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"):
self.local_user = models.User.objects.create_user(
"mouse@local.com",
"mouse@your.domain.here",
"mouse@mouse.com",
"password",
local=True,
@ -31,7 +31,9 @@ class AuthenticationViews(TestCase):
self.anonymous_user = AnonymousUser
self.anonymous_user.is_authenticated = False
self.settings = models.SiteSettings.objects.create(id=1)
self.settings = models.SiteSettings.objects.create(
id=1, require_confirm_email=False
)
def test_login_get(self, _):
"""there are so many views, this just makes sure it LOADS"""
@ -49,6 +51,66 @@ class AuthenticationViews(TestCase):
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)
def test_login_post_localname(self, _):
"""there are so many views, this just makes sure it LOADS"""
view = views.Login.as_view()
form = forms.LoginForm()
form.data["localname"] = "mouse@mouse.com"
form.data["password"] = "password"
request = self.factory.post("", form.data)
request.user = self.anonymous_user
with patch("bookwyrm.views.authentication.login"):
result = view(request)
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)
def test_login_post_username(self, _):
"""there are so many views, this just makes sure it LOADS"""
view = views.Login.as_view()
form = forms.LoginForm()
form.data["localname"] = "mouse@your.domain.here"
form.data["password"] = "password"
request = self.factory.post("", form.data)
request.user = self.anonymous_user
with patch("bookwyrm.views.authentication.login"):
result = view(request)
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)
def test_login_post_email(self, _):
"""there are so many views, this just makes sure it LOADS"""
view = views.Login.as_view()
form = forms.LoginForm()
form.data["localname"] = "mouse"
form.data["password"] = "password"
request = self.factory.post("", form.data)
request.user = self.anonymous_user
with patch("bookwyrm.views.authentication.login"):
result = view(request)
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)
def test_login_post_invalid_credentials(self, _):
"""there are so many views, this just makes sure it LOADS"""
view = views.Login.as_view()
form = forms.LoginForm()
form.data["localname"] = "mouse"
form.data["password"] = "passsword1"
request = self.factory.post("", form.data)
request.user = self.anonymous_user
with patch("bookwyrm.views.authentication.login"):
result = view(request)
result.render()
self.assertEqual(result.status_code, 200)
self.assertEqual(
result.context_data["login_form"].non_field_errors,
"Username or password are incorrect",
)
def test_register(self, _):
"""create a user"""
view = views.Register.as_view()
@ -70,6 +132,33 @@ class AuthenticationViews(TestCase):
self.assertEqual(nutria.localname, "nutria-user.user_nutria")
self.assertEqual(nutria.local, True)
@patch("bookwyrm.emailing.send_email.delay")
def test_register_email_confirm(self, *_):
"""create a user"""
self.settings.require_confirm_email = True
self.settings.save()
view = views.Register.as_view()
self.assertEqual(models.User.objects.count(), 1)
request = self.factory.post(
"register/",
{
"localname": "nutria",
"password": "mouseword",
"email": "aa@bb.cccc",
},
)
with patch("bookwyrm.views.authentication.login"):
response = view(request)
self.assertEqual(response.status_code, 302)
nutria = models.User.objects.get(localname="nutria")
self.assertEqual(nutria.username, "nutria@%s" % DOMAIN)
self.assertEqual(nutria.local, True)
self.assertFalse(nutria.is_active)
self.assertEqual(nutria.deactivation_reason, "pending")
self.assertIsNotNone(nutria.confirmation_code)
def test_register_trailing_space(self, _):
"""django handles this so weirdly"""
view = views.Register.as_view()
@ -189,3 +278,74 @@ class AuthenticationViews(TestCase):
with self.assertRaises(Http404):
response = view(request)
self.assertEqual(models.User.objects.count(), 2)
def test_confirm_email_code_get(self, _):
"""there are so many views, this just makes sure it LOADS"""
self.settings.require_confirm_email = True
self.settings.save()
self.local_user.is_active = False
self.local_user.deactivation_reason = "pending"
self.local_user.confirmation_code = "12345"
self.local_user.save(
broadcast=False,
update_fields=["is_active", "deactivation_reason", "confirmation_code"],
)
view = views.ConfirmEmailCode.as_view()
request = self.factory.get("")
request.user = self.anonymous_user
result = view(request, "12345")
self.assertEqual(result.url, "/login/confirmed")
self.assertEqual(result.status_code, 302)
self.local_user.refresh_from_db()
self.assertTrue(self.local_user.is_active)
self.assertIsNone(self.local_user.deactivation_reason)
request.user = self.local_user
result = view(request, "12345")
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)
def test_confirm_email_code_get_invalid_code(self, _):
"""there are so many views, this just makes sure it LOADS"""
self.settings.require_confirm_email = True
self.settings.save()
self.local_user.is_active = False
self.local_user.deactivation_reason = "pending"
self.local_user.confirmation_code = "12345"
self.local_user.save(
broadcast=False,
update_fields=["is_active", "deactivation_reason", "confirmation_code"],
)
view = views.ConfirmEmailCode.as_view()
request = self.factory.get("")
request.user = self.anonymous_user
result = view(request, "abcde")
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
self.assertFalse(self.local_user.is_active)
self.assertEqual(self.local_user.deactivation_reason, "pending")
def test_confirm_email_get(self, _):
"""there are so many views, this just makes sure it LOADS"""
self.settings.require_confirm_email = True
self.settings.save()
login = views.ConfirmEmail.as_view()
request = self.factory.get("")
request.user = self.anonymous_user
result = login(request)
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
request.user = self.local_user
result = login(request)
self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302)

View file

@ -12,6 +12,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile
from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
from django.utils import timezone
from bookwyrm import forms, models, views
from bookwyrm.activitypub import ActivitypubResponse
@ -52,6 +53,11 @@ class BookViews(TestCase):
def test_book_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Book.as_view()
models.ReadThrough.objects.create(
user=self.local_user,
book=self.book,
start_date=timezone.now(),
)
request = self.factory.get("")
request.user = self.local_user
with patch("bookwyrm.views.books.is_api_request") as is_api:
@ -67,6 +73,79 @@ class BookViews(TestCase):
self.assertIsInstance(result, ActivitypubResponse)
self.assertEqual(result.status_code, 200)
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_book_page_statuses(self, *_):
"""there are so many views, this just makes sure it LOADS"""
view = views.Book.as_view()
review = models.Review.objects.create(
user=self.local_user,
book=self.book,
content="hi",
)
comment = models.Comment.objects.create(
user=self.local_user,
book=self.book,
content="hi",
)
quote = models.Quotation.objects.create(
user=self.local_user,
book=self.book,
content="hi",
quote="wow",
)
request = self.factory.get("")
request.user = self.local_user
with patch("bookwyrm.views.books.is_api_request") as is_api:
is_api.return_value = False
result = view(request, self.book.id, user_statuses="review")
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
self.assertEqual(result.context_data["statuses"].object_list[0], review)
with patch("bookwyrm.views.books.is_api_request") as is_api:
is_api.return_value = False
result = view(request, self.book.id, user_statuses="comment")
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
self.assertEqual(result.context_data["statuses"].object_list[0], comment)
with patch("bookwyrm.views.books.is_api_request") as is_api:
is_api.return_value = False
result = view(request, self.book.id, user_statuses="quotation")
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
self.assertEqual(result.context_data["statuses"].object_list[0], quote)
def test_book_page_invalid_id(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Book.as_view()
request = self.factory.get("")
request.user = self.local_user
with patch("bookwyrm.views.books.is_api_request") as is_api:
is_api.return_value = False
result = view(request, 0)
self.assertEqual(result.status_code, 404)
def test_book_page_work_id(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Book.as_view()
request = self.factory.get("")
request.user = self.local_user
with patch("bookwyrm.views.books.is_api_request") as is_api:
is_api.return_value = False
result = view(request, self.work.id)
result.render()
self.assertEqual(result.status_code, 200)
self.assertEqual(result.context_data["book"], self.book)
def test_edit_book_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.EditBook.as_view()

View file

@ -1,11 +1,12 @@
""" test for app action functionality """
import pathlib
from unittest.mock import patch
from django.core.files.uploadedfile import SimpleUploadedFile
from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
from bookwyrm import models
from bookwyrm import views
from bookwyrm import forms, models, views
class ImportViews(TestCase):
@ -47,6 +48,27 @@ class ImportViews(TestCase):
result.render()
self.assertEqual(result.status_code, 200)
def test_start_import(self):
"""retry failed items"""
view = views.Import.as_view()
form = forms.ImportForm()
form.data["source"] = "LibraryThing"
form.data["privacy"] = "public"
form.data["include_reviews"] = False
csv_file = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
form.data["csv_file"] = SimpleUploadedFile(
csv_file, open(csv_file, "rb").read(), content_type="text/csv"
)
request = self.factory.post("", form.data)
request.user = self.local_user
with patch("bookwyrm.importers.Importer.start_import"):
view(request)
job = models.ImportJob.objects.get()
self.assertFalse(job.include_reviews)
self.assertEqual(job.privacy, "public")
def test_retry_import(self):
"""retry failed items"""
view = views.ImportStatus.as_view()

View file

@ -52,6 +52,26 @@ class InviteViews(TestCase):
result.render()
self.assertEqual(result.status_code, 200)
def test_manage_invites_post(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.ManageInvites.as_view()
form = forms.CreateInviteForm()
form.data["use_limit"] = 3
form.data["expiry"] = ""
request = self.factory.post("", form.data)
request.user = self.local_user
request.user.is_superuser = True
result = view(request)
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
invite = models.SiteInvite.objects.get()
self.assertEqual(invite.use_limit, 3)
self.assertIsNone(invite.expiry)
def test_invite_request(self):
"""request to join a server"""
form = forms.InviteRequestForm()

View file

@ -46,7 +46,15 @@ urlpatterns = [
re_path("^api/updates/stream/(?P<stream>[a-z]+)/?$", views.get_unread_status_count),
# authentication
re_path(r"^login/?$", views.Login.as_view(), name="login"),
re_path(r"^login/(?P<confirmed>confirmed)?$", views.Login.as_view(), name="login"),
re_path(r"^register/?$", views.Register.as_view()),
re_path(r"confirm-email/?$", views.ConfirmEmail.as_view(), name="confirm-email"),
re_path(
r"confirm-email/(?P<code>[A-Za-z0-9]+)/?$",
views.ConfirmEmailCode.as_view(),
name="confirm-email-code",
),
re_path(r"resend-link", views.resend_link, name="resend-link"),
re_path(r"^logout/?$", views.Logout.as_view(), name="logout"),
re_path(
r"^password-reset/?$",

View file

@ -1,6 +1,7 @@
""" make sure all our nice views are available """
from .announcements import Announcements, Announcement, delete_announcement
from .authentication import Login, Register, Logout
from .authentication import ConfirmEmail, ConfirmEmailCode, resend_link
from .author import Author, EditAuthor
from .block import Block, unblock
from .books import Book, EditBook, ConfirmEditBook, Editions

View file

@ -6,24 +6,27 @@ from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.views import View
from bookwyrm import forms, models
from bookwyrm import emailing, forms, models
from bookwyrm.settings import DOMAIN
# pylint: disable= no-self-use
# pylint: disable=no-self-use
@method_decorator(csrf_exempt, name="dispatch")
class Login(View):
"""authenticate an existing user"""
def get(self, request):
def get(self, request, confirmed=None):
"""login page"""
if request.user.is_authenticated:
return redirect("/")
# sene user to the login page
# send user to the login page
data = {
"show_confirmed_email": confirmed,
"login_form": forms.LoginForm(),
"register_form": forms.RegisterForm(),
}
@ -37,35 +40,55 @@ class Login(View):
localname = login_form.data["localname"]
if "@" in localname: # looks like an email address to me
email = localname
try:
username = models.User.objects.get(email=email)
username = models.User.objects.get(email=localname).username
except models.User.DoesNotExist: # maybe it's a full username?
username = localname
else:
username = "%s@%s" % (localname, DOMAIN)
password = login_form.data["password"]
# perform authentication
user = authenticate(request, username=username, password=password)
if user is not None:
# successful login
login(request, user)
user.last_active_date = timezone.now()
user.save(broadcast=False, update_fields=["last_active_date"])
if request.POST.get("first_login"):
return redirect("get-started-profile")
return redirect(request.GET.get("next", "/"))
# maybe the user is pending email confirmation
if models.User.objects.filter(
username=username, is_active=False, deactivation_reason="pending"
).exists():
return redirect("confirm-email")
# login errors
login_form.non_field_errors = "Username or password are incorrect"
login_form.non_field_errors = _("Username or password are incorrect")
register_form = forms.RegisterForm()
data = {"login_form": login_form, "register_form": register_form}
return TemplateResponse(request, "login.html", data)
@method_decorator(login_required, name="dispatch")
class Logout(View):
"""log out"""
def get(self, request):
"""done with this place! outa here!"""
logout(request)
return redirect("/")
class Register(View):
"""register a user"""
def post(self, request):
"""join the server"""
if not models.SiteSettings.get().allow_registration:
settings = models.SiteSettings.get()
if not settings.allow_registration:
invite_code = request.POST.get("invite_code")
if not invite_code:
@ -104,22 +127,76 @@ class Register(View):
username = "%s@%s" % (localname, DOMAIN)
user = models.User.objects.create_user(
username, email, password, localname=localname, local=True
username,
email,
password,
localname=localname,
local=True,
deactivation_reason="pending" if settings.require_confirm_email else None,
is_active=not settings.require_confirm_email,
)
if invite:
invite.times_used += 1
invite.invitees.add(user)
invite.save()
if settings.require_confirm_email:
emailing.email_confirmation_email(user)
return redirect("confirm-email")
login(request, user)
return redirect("get-started-profile")
@method_decorator(login_required, name="dispatch")
class Logout(View):
"""log out"""
class ConfirmEmailCode(View):
"""confirm email address"""
def get(self, request):
"""done with this place! outa here!"""
logout(request)
return redirect("/")
def get(self, request, code): # pylint: disable=unused-argument
"""you got the code! good work"""
settings = models.SiteSettings.get()
if request.user.is_authenticated or not settings.require_confirm_email:
return redirect("/")
# look up the user associated with this code
try:
user = models.User.objects.get(confirmation_code=code)
except models.User.DoesNotExist:
return TemplateResponse(
request, "confirm_email/confirm_email.html", {"valid": False}
)
# update the user
user.is_active = True
user.deactivation_reason = None
user.save(broadcast=False, update_fields=["is_active", "deactivation_reason"])
# direct the user to log in
return redirect("login", confirmed="confirmed")
class ConfirmEmail(View):
"""enter code to confirm email address"""
def get(self, request): # pylint: disable=unused-argument
"""you need a code! keep looking"""
settings = models.SiteSettings.get()
if request.user.is_authenticated or not settings.require_confirm_email:
return redirect("/")
return TemplateResponse(
request, "confirm_email/confirm_email.html", {"valid": True}
)
def post(self, request):
"""same as clicking the link"""
code = request.POST.get("code")
return ConfirmEmailCode().get(request, code)
@require_POST
def resend_link(request):
"""resend confirmation link"""
email = request.POST.get("email")
user = get_object_or_404(models.User, email=email)
emailing.email_confirmation_email(user)
return TemplateResponse(
request, "confirm_email/confirm_email.html", {"valid": True}
)

View file

@ -65,6 +65,13 @@ class Book(View):
queryset = queryset.select_related("user")
paginated = Paginator(queryset, PAGE_LENGTH)
lists = privacy_filter(
request.user,
models.List.objects.filter(
listitem__approved=True,
listitem__book__in=book.parent_work.editions.all(),
),
)
data = {
"book": book,
"statuses": paginated.get_page(request.GET.get("page")),
@ -75,9 +82,7 @@ class Book(View):
if not user_statuses
else None,
"rating": reviews.aggregate(Avg("rating"))["rating__avg"],
"lists": privacy_filter(
request.user, book.list_set.filter(listitem__approved=True)
),
"lists": lists,
}
if request.user.is_authenticated:

View file

@ -46,4 +46,6 @@ def email_preview(request):
data["text_content_path"] = "email/{}/text_content.html".format(template)
data["reset_link"] = "https://example.com/link"
data["invite_link"] = "https://example.com/link"
data["confirmation_link"] = "https://example.com/link"
data["confirmation_code"] = "AKJHKDGKJSDFG"
return TemplateResponse(request, "email/preview.html", data)

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-03-02 17:19-0800\n"
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
"Language-Team: English <LL@li.org>\n"
@ -306,7 +306,7 @@ msgstr ""
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -739,6 +739,58 @@ msgstr "Schließen"
msgid "Compose status"
msgstr "Status teilen"
#: bookwyrm/templates/confirm_email/confirm_email.html:4
#, fuzzy
#| msgid "Confirm"
msgid "Confirm email"
msgstr "Bestätigen"
#: bookwyrm/templates/confirm_email/confirm_email.html:7
#, fuzzy
#| msgid "Email address:"
msgid "Confirm your email address"
msgstr "E-Mail Adresse"
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
#, fuzzy
#| msgid "Confirm password:"
msgid "Confirmation code:"
msgstr "Passwort bestätigen:"
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Absenden"
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "E-Mail Adresse"
#: bookwyrm/templates/confirm_email/resend_form.html:17
msgid "Resend link"
msgstr ""
#: bookwyrm/templates/directory/community_filter.html:5
#, fuzzy
#| msgid "Comment"
@ -882,7 +934,7 @@ msgid "Join %(name)s"
msgstr "Tritt %(name)s bei"
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr "Diese Instanz ist geschlossen"
@ -894,22 +946,26 @@ msgstr ""
msgid "Request an Invitation"
msgstr ""
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "E-Mail Adresse"
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Absenden"
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr "Dein Account"
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
#, fuzzy
#| msgid "Confirm"
msgid "Confirm Email"
msgstr "Bestätigen"
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1342,7 +1398,7 @@ msgid "Imported"
msgstr "Importiert"
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr "Erstelle einen Account"
@ -1412,7 +1468,7 @@ msgid "Notifications"
msgstr "Benachrichtigungen"
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr ""
@ -1421,12 +1477,12 @@ msgstr ""
msgid "password"
msgstr "Passwort"
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr "Passwort vergessen?"
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr "Anmelden"
@ -1619,16 +1675,20 @@ msgstr "Deine Listen"
msgid "Login"
msgstr ""
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr "Passwort:"
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr "Kontaktiere für eine Einladung eine*n Admin"
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr "Mehr über diese Seite"
@ -2554,7 +2614,15 @@ msgstr "Registrierungen erlauben"
msgid "Allow invite requests"
msgstr "Folgeanfragen"
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr "Registrierungen geschlossen text"
@ -3295,6 +3363,10 @@ msgstr ""
msgid "%(title)s: %(subtitle)s"
msgstr ""
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
#, fuzzy
#| msgid "Email address:"
@ -3371,11 +3443,6 @@ msgstr ""
#~ msgid "Enter a valid integer."
#~ msgstr "E-Mail Adresse"
#, fuzzy
#~| msgid "Email address:"
#~ msgid "Enter a valid email address."
#~ msgstr "E-Mail Adresse"
#, fuzzy
#~| msgid "Email address:"
#~ msgid "Enter a valid IPv4 address."

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
"Language-Team: English <LL@li.org>\n"
@ -282,7 +282,7 @@ msgstr ""
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -680,6 +680,52 @@ msgstr ""
msgid "Compose status"
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:4
msgid "Confirm email"
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:7
msgid "Confirm your email address"
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
msgid "Confirmation code:"
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:17
msgid "Resend link"
msgstr ""
#: bookwyrm/templates/directory/community_filter.html:5
msgid "Community"
msgstr ""
@ -806,7 +852,7 @@ msgid "Join %(name)s"
msgstr ""
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr ""
@ -818,22 +864,24 @@ msgstr ""
msgid "Request an Invitation"
msgstr ""
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr ""
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr ""
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
msgid "Confirm Email"
msgstr ""
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1235,7 +1283,7 @@ msgid "Imported"
msgstr ""
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr ""
@ -1303,7 +1351,7 @@ msgid "Notifications"
msgstr ""
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr ""
@ -1312,12 +1360,12 @@ msgstr ""
msgid "password"
msgstr ""
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr ""
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr ""
@ -1493,16 +1541,20 @@ msgstr ""
msgid "Login"
msgstr ""
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr ""
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr ""
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr ""
@ -2315,7 +2367,15 @@ msgstr ""
msgid "Allow invite requests"
msgstr ""
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr ""
@ -2991,6 +3051,10 @@ msgstr ""
msgid "%(title)s: %(subtitle)s"
msgstr ""
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
msgid "Not a valid csv file"
msgstr ""

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-03-19 11:49+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -288,7 +288,7 @@ msgstr "Clave Goodreads:"
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -688,6 +688,60 @@ msgstr "Cerrar"
msgid "Compose status"
msgstr "Componer status"
#: bookwyrm/templates/confirm_email/confirm_email.html:4
#, fuzzy
#| msgid "Confirm"
msgid "Confirm email"
msgstr "Confirmar"
#: bookwyrm/templates/confirm_email/confirm_email.html:7
#, fuzzy
#| msgid "Enter a valid email address."
msgid "Confirm your email address"
msgstr "Ingrese una dirección de correo electrónico válida."
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
#, fuzzy
#| msgid "Confirm password:"
msgid "Confirmation code:"
msgstr "Confirmar contraseña:"
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Enviar"
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "Dirección de correo electrónico:"
#: bookwyrm/templates/confirm_email/resend_form.html:17
#, fuzzy
#| msgid "Re-send invite"
msgid "Resend link"
msgstr "Re-enviar invitación"
#: bookwyrm/templates/directory/community_filter.html:5
msgid "Community"
msgstr "Comunidad"
@ -816,7 +870,7 @@ msgid "Join %(name)s"
msgstr "Unirse con %(name)s"
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr "Esta instancia está cerrada."
@ -828,22 +882,26 @@ msgstr "¡Gracias! Tu solicitud ha sido recibido."
msgid "Request an Invitation"
msgstr "Solicitar una invitación"
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "Dirección de correo electrónico:"
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Enviar"
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr "Tu cuenta"
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
#, fuzzy
#| msgid "Confirm"
msgid "Confirm Email"
msgstr "Confirmar"
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1250,7 +1308,7 @@ msgid "Imported"
msgstr "Importado"
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr "Crear una cuenta"
@ -1318,7 +1376,7 @@ msgid "Notifications"
msgstr "Notificaciones"
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr "Nombre de usuario:"
@ -1327,12 +1385,12 @@ msgstr "Nombre de usuario:"
msgid "password"
msgstr "contraseña"
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr "¿Olvidaste tu contraseña?"
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr "Iniciar sesión"
@ -1510,16 +1568,20 @@ msgstr "Tus listas"
msgid "Login"
msgstr "Iniciar sesión"
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr "Contraseña:"
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr "Contactar a unx administradorx para recibir una invitación"
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr "Más sobre este sitio"
@ -2351,7 +2413,15 @@ msgstr "Permitir registración:"
msgid "Allow invite requests"
msgstr "Permitir solicitudes de invitación:"
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr "Texto de registración cerrada:"
@ -3036,6 +3106,10 @@ msgstr ""
msgid "%(title)s: %(subtitle)s"
msgstr ""
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
msgid "Not a valid csv file"
msgstr "No un archivo csv válido"
@ -3113,9 +3187,6 @@ msgstr "Un enlace para reestablecer tu contraseña se enviará a %s"
#~ msgid "Enter a valid integer."
#~ msgstr "Ingrese un entero válido."
#~ msgid "Enter a valid email address."
#~ msgstr "Ingrese una dirección de correo electrónico válida."
#~ msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens."
#~ msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-04-05 12:44+0100\n"
"Last-Translator: Fabien Basmaison <contact@arkhi.org>\n"
"Language-Team: Mouse Reeve <LL@li.org>\n"
@ -286,7 +286,7 @@ msgstr "Clé Goodreads:"
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -684,6 +684,60 @@ msgstr "Fermer"
msgid "Compose status"
msgstr "Rédiger un statut"
#: bookwyrm/templates/confirm_email/confirm_email.html:4
#, fuzzy
#| msgid "Confirm"
msgid "Confirm email"
msgstr "Confirmer"
#: bookwyrm/templates/confirm_email/confirm_email.html:7
#, fuzzy
#| msgid "Email address:"
msgid "Confirm your email address"
msgstr "Adresse email:"
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
#, fuzzy
#| msgid "Confirm password:"
msgid "Confirmation code:"
msgstr "Confirmez le mot de passe:"
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Valider"
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "Adresse email:"
#: bookwyrm/templates/confirm_email/resend_form.html:17
#, fuzzy
#| msgid "Re-send invite"
msgid "Resend link"
msgstr "Envoyer linvitation de nouveau"
#: bookwyrm/templates/directory/community_filter.html:5
msgid "Community"
msgstr "Communauté"
@ -812,7 +866,7 @@ msgid "Join %(name)s"
msgstr "Rejoignez %(name)s"
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr "Cette instance est fermée"
@ -824,22 +878,26 @@ msgstr "Merci! Votre demande a bien été reçue."
msgid "Request an Invitation"
msgstr "Demander une invitation"
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "Adresse email:"
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "Valider"
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr "Votre compte"
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
#, fuzzy
#| msgid "Confirm"
msgid "Confirm Email"
msgstr "Confirmer"
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1246,7 +1304,7 @@ msgid "Imported"
msgstr "Importé"
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr "Créer un compte"
@ -1314,7 +1372,7 @@ msgid "Notifications"
msgstr "Notifications"
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr "Nom du compte:"
@ -1323,12 +1381,12 @@ msgstr "Nom du compte:"
msgid "password"
msgstr "Mot de passe"
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr "Mot de passe oublié?"
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr "Se connecter"
@ -1504,16 +1562,20 @@ msgstr "Vos listes"
msgid "Login"
msgstr "Connexion"
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr "Mot de passe:"
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr "Contacter un administrateur pour obtenir une invitation"
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr "En savoir plus sur ce site"
@ -2333,7 +2395,15 @@ msgstr "Autoriser les inscriptions"
msgid "Allow invite requests"
msgstr "Autoriser les demandes dinvitation"
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr "Texte affiché lorsque les inscriptions sont closes:"
@ -3015,6 +3085,10 @@ msgstr "Ce fichier dépasse la taille limite: 10Mo"
msgid "%(title)s: %(subtitle)s"
msgstr "%(title)s (%(subtitle)s)"
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
msgid "Not a valid csv file"
msgstr "Fichier CSV non valide"
@ -3062,11 +3136,6 @@ msgstr "Un lien de réinitialisation a été envoyé à %s."
#~ msgid "Enter a valid integer."
#~ msgstr "Adresse email:"
#, fuzzy
#~| msgid "Email address:"
#~ msgid "Enter a valid email address."
#~ msgstr "Adresse email:"
#, fuzzy
#~| msgid "Email address:"
#~ msgid "Enter a valid IPv4 address."

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-03-20 00:56+0000\n"
"Last-Translator: Kana <gudzpoz@live.com>\n"
"Language-Team: Mouse Reeve <LL@li.org>\n"
@ -284,7 +284,7 @@ msgstr "Goodreads key:"
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -681,6 +681,60 @@ msgstr "关闭"
msgid "Compose status"
msgstr "撰写状态"
#: bookwyrm/templates/confirm_email/confirm_email.html:4
#, fuzzy
#| msgid "Confirm"
msgid "Confirm email"
msgstr "确认"
#: bookwyrm/templates/confirm_email/confirm_email.html:7
#, fuzzy
#| msgid "Email address:"
msgid "Confirm your email address"
msgstr "邮箱地址:"
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
#, fuzzy
#| msgid "Confirm password:"
msgid "Confirmation code:"
msgstr "确认密码:"
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "提交"
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "邮箱地址:"
#: bookwyrm/templates/confirm_email/resend_form.html:17
#, fuzzy
#| msgid "Re-send invite"
msgid "Resend link"
msgstr "重新发送请求"
#: bookwyrm/templates/directory/community_filter.html:5
msgid "Community"
msgstr "社区"
@ -807,7 +861,7 @@ msgid "Join %(name)s"
msgstr "加入 %(name)s"
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr "本实例不开放。"
@ -819,22 +873,26 @@ msgstr "谢谢你!我们已经收到了你的请求。"
msgid "Request an Invitation"
msgstr "请求邀请"
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "邮箱地址:"
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "提交"
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr "你的帐号"
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
#, fuzzy
#| msgid "Confirm"
msgid "Confirm Email"
msgstr "确认"
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1237,7 +1295,7 @@ msgid "Imported"
msgstr "已导入"
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr "创建帐号"
@ -1305,7 +1363,7 @@ msgid "Notifications"
msgstr "通知"
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr "用户名:"
@ -1314,12 +1372,12 @@ msgstr "用户名:"
msgid "password"
msgstr "密码"
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr "忘记了密码?"
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr "登录"
@ -1495,16 +1553,20 @@ msgstr "你的列表"
msgid "Login"
msgstr "登录"
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr "密码:"
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr "联系管理员以取得邀请"
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr "更多关于本站点的信息"
@ -2319,7 +2381,15 @@ msgstr "允许注册"
msgid "Allow invite requests"
msgstr "允许请求邀请"
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr "注册关闭文字:"
@ -2992,6 +3062,10 @@ msgstr "文件超过了最大大小: 10MB"
msgid "%(title)s: %(subtitle)s"
msgstr "%(title)s%(subtitle)s"
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
msgid "Not a valid csv file"
msgstr "不是有效的 csv 文件"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-05 01:33+0000\n"
"POT-Creation-Date: 2021-08-07 01:35+0000\n"
"PO-Revision-Date: 2021-06-30 10:36+0000\n"
"Last-Translator: Grace Cheng <chengracecwy@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -288,7 +288,7 @@ msgstr "Goodreads key:"
#: bookwyrm/templates/settings/announcement_form.html:69
#: bookwyrm/templates/settings/edit_server.html:68
#: bookwyrm/templates/settings/federated_server.html:98
#: bookwyrm/templates/settings/site.html:101
#: bookwyrm/templates/settings/site.html:108
#: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42
#: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36
@ -687,6 +687,60 @@ msgstr "關閉"
msgid "Compose status"
msgstr "撰寫狀態"
#: bookwyrm/templates/confirm_email/confirm_email.html:4
#, fuzzy
#| msgid "Confirm"
msgid "Confirm email"
msgstr "確認"
#: bookwyrm/templates/confirm_email/confirm_email.html:7
#, fuzzy
#| msgid "Email address:"
msgid "Confirm your email address"
msgstr "郵箱地址:"
#: bookwyrm/templates/confirm_email/confirm_email.html:13
msgid "A confirmation code has been sent to the email address you used to register your account."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:15
msgid "Sorry! We couldn't find that code."
msgstr ""
#: bookwyrm/templates/confirm_email/confirm_email.html:19
#, fuzzy
#| msgid "Confirm password:"
msgid "Confirmation code:"
msgstr "確認密碼:"
#: bookwyrm/templates/confirm_email/confirm_email.html:25
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "提交"
#: bookwyrm/templates/confirm_email/confirm_email.html:32
msgid "Can't find your code?"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:4
msgid "Resend confirmation link"
msgstr ""
#: bookwyrm/templates/confirm_email/resend_form.html:11
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "郵箱地址:"
#: bookwyrm/templates/confirm_email/resend_form.html:17
#, fuzzy
#| msgid "Re-send invite"
msgid "Resend link"
msgstr "重新發送請求"
#: bookwyrm/templates/directory/community_filter.html:5
msgid "Community"
msgstr "社群"
@ -813,7 +867,7 @@ msgid "Join %(name)s"
msgstr "加入 %(name)s"
#: bookwyrm/templates/discover/landing_layout.html:51
#: bookwyrm/templates/login.html:51
#: bookwyrm/templates/login.html:56
msgid "This instance is closed"
msgstr "本實例不開放。"
@ -825,22 +879,26 @@ msgstr "謝謝你!我們已經受到了你的請求。"
msgid "Request an Invitation"
msgstr "請求邀請"
#: bookwyrm/templates/discover/landing_layout.html:64
#: bookwyrm/templates/password_reset_request.html:18
#: bookwyrm/templates/preferences/edit_user.html:38
#: bookwyrm/templates/snippets/register_form.html:13
msgid "Email address:"
msgstr "郵箱地址:"
#: bookwyrm/templates/discover/landing_layout.html:70
#: bookwyrm/templates/moderation/report_modal.html:33
msgid "Submit"
msgstr "提交"
#: bookwyrm/templates/discover/landing_layout.html:79
msgid "Your Account"
msgstr "你的帳號"
#: bookwyrm/templates/email/confirm/html_content.html:6
#: bookwyrm/templates/email/confirm/text_content.html:4
#, python-format
msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:"
msgstr ""
#: bookwyrm/templates/email/confirm/html_content.html:11
#, fuzzy
#| msgid "Confirm"
msgid "Confirm Email"
msgstr "確認"
#: bookwyrm/templates/email/confirm/subject.html:2
msgid "Please confirm your email"
msgstr ""
#: bookwyrm/templates/email/html_layout.html:15
#: bookwyrm/templates/email/text_layout.html:2
msgid "Hi there,"
@ -1247,7 +1305,7 @@ msgid "Imported"
msgstr "已匯入"
#: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12
#: bookwyrm/templates/login.html:46
#: bookwyrm/templates/login.html:51
msgid "Create an Account"
msgstr "建立帳號"
@ -1315,7 +1373,7 @@ msgid "Notifications"
msgstr "通知"
#: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162
#: bookwyrm/templates/login.html:17
#: bookwyrm/templates/login.html:22
#: bookwyrm/templates/snippets/register_form.html:4
msgid "Username:"
msgstr "使用者名稱:"
@ -1324,12 +1382,12 @@ msgstr "使用者名稱:"
msgid "password"
msgstr "密碼"
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36
#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41
msgid "Forgot your password?"
msgstr "忘記了密碼?"
#: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10
#: bookwyrm/templates/login.html:33
#: bookwyrm/templates/login.html:38
msgid "Log in"
msgstr "登入"
@ -1505,16 +1563,20 @@ msgstr "你的列表"
msgid "Login"
msgstr "登入"
#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/login.html:16
msgid "Success! Email address confirmed."
msgstr ""
#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17
#: bookwyrm/templates/snippets/register_form.html:22
msgid "Password:"
msgstr "密碼:"
#: bookwyrm/templates/login.html:52
#: bookwyrm/templates/login.html:57
msgid "Contact an administrator to get an invite"
msgstr "聯絡管理員以取得邀請"
#: bookwyrm/templates/login.html:63
#: bookwyrm/templates/login.html:68
msgid "More about this site"
msgstr "關於本網站的更多"
@ -2338,7 +2400,15 @@ msgstr "允許註冊:"
msgid "Allow invite requests"
msgstr "允許請求邀請:"
#: bookwyrm/templates/settings/site.html:95
#: bookwyrm/templates/settings/site.html:97
msgid "Require users to confirm email address"
msgstr ""
#: bookwyrm/templates/settings/site.html:99
msgid "(Recommended if registration is open)"
msgstr ""
#: bookwyrm/templates/settings/site.html:102
msgid "Registration closed text:"
msgstr "註冊關閉文字:"
@ -3011,6 +3081,10 @@ msgstr "檔案超過了最大大小: 10MB"
msgid "%(title)s: %(subtitle)s"
msgstr ""
#: bookwyrm/views/authentication.py:69
msgid "Username or password are incorrect"
msgstr ""
#: bookwyrm/views/import_data.py:67
msgid "Not a valid csv file"
msgstr "不是有效的 csv 檔案"