mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-27 20:11:14 +00:00
Merge branch 'main' into font-end-accessibility-improvements
This commit is contained in:
commit
c0ac838ed8
37 changed files with 576 additions and 146 deletions
|
@ -22,6 +22,11 @@ class ActivityStream(RedisStore):
|
||||||
stream_id = self.stream_id(user)
|
stream_id = self.stream_id(user)
|
||||||
return f"{stream_id}-unread"
|
return f"{stream_id}-unread"
|
||||||
|
|
||||||
|
def unread_by_status_type_id(self, user):
|
||||||
|
"""the redis key for this user's unread count for this stream"""
|
||||||
|
stream_id = self.stream_id(user)
|
||||||
|
return f"{stream_id}-unread-by-type"
|
||||||
|
|
||||||
def get_rank(self, obj): # pylint: disable=no-self-use
|
def get_rank(self, obj): # pylint: disable=no-self-use
|
||||||
"""statuses are sorted by date published"""
|
"""statuses are sorted by date published"""
|
||||||
return obj.published_date.timestamp()
|
return obj.published_date.timestamp()
|
||||||
|
@ -35,6 +40,10 @@ class ActivityStream(RedisStore):
|
||||||
for user in self.get_audience(status):
|
for user in self.get_audience(status):
|
||||||
# add to the unread status count
|
# add to the unread status count
|
||||||
pipeline.incr(self.unread_id(user))
|
pipeline.incr(self.unread_id(user))
|
||||||
|
# add to the unread status count for status type
|
||||||
|
pipeline.hincrby(
|
||||||
|
self.unread_by_status_type_id(user), get_status_type(status), 1
|
||||||
|
)
|
||||||
|
|
||||||
# and go!
|
# and go!
|
||||||
pipeline.execute()
|
pipeline.execute()
|
||||||
|
@ -55,6 +64,7 @@ class ActivityStream(RedisStore):
|
||||||
"""load the statuses to be displayed"""
|
"""load the statuses to be displayed"""
|
||||||
# clear unreads for this feed
|
# clear unreads for this feed
|
||||||
r.set(self.unread_id(user), 0)
|
r.set(self.unread_id(user), 0)
|
||||||
|
r.delete(self.unread_by_status_type_id(user))
|
||||||
|
|
||||||
statuses = self.get_store(self.stream_id(user))
|
statuses = self.get_store(self.stream_id(user))
|
||||||
return (
|
return (
|
||||||
|
@ -75,6 +85,14 @@ class ActivityStream(RedisStore):
|
||||||
"""get the unread status count for this user's feed"""
|
"""get the unread status count for this user's feed"""
|
||||||
return int(r.get(self.unread_id(user)) or 0)
|
return int(r.get(self.unread_id(user)) or 0)
|
||||||
|
|
||||||
|
def get_unread_count_by_status_type(self, user):
|
||||||
|
"""get the unread status count for this user's feed's status types"""
|
||||||
|
status_types = r.hgetall(self.unread_by_status_type_id(user))
|
||||||
|
return {
|
||||||
|
str(key.decode("utf-8")): int(value) or 0
|
||||||
|
for key, value in status_types.items()
|
||||||
|
}
|
||||||
|
|
||||||
def populate_streams(self, user):
|
def populate_streams(self, user):
|
||||||
"""go from zero to a timeline"""
|
"""go from zero to a timeline"""
|
||||||
self.populate_store(self.stream_id(user))
|
self.populate_store(self.stream_id(user))
|
||||||
|
@ -460,7 +478,7 @@ def remove_status_task(status_ids):
|
||||||
@app.task(queue=HIGH)
|
@app.task(queue=HIGH)
|
||||||
def add_status_task(status_id, increment_unread=False):
|
def add_status_task(status_id, increment_unread=False):
|
||||||
"""add a status to any stream it should be in"""
|
"""add a status to any stream it should be in"""
|
||||||
status = models.Status.objects.get(id=status_id)
|
status = models.Status.objects.select_subclasses().get(id=status_id)
|
||||||
# we don't want to tick the unread count for csv import statuses, idk how better
|
# we don't want to tick the unread count for csv import statuses, idk how better
|
||||||
# to check than just to see if the states is more than a few days old
|
# to check than just to see if the states is more than a few days old
|
||||||
if status.created_date < timezone.now() - timedelta(days=2):
|
if status.created_date < timezone.now() - timedelta(days=2):
|
||||||
|
@ -507,3 +525,20 @@ def handle_boost_task(boost_id):
|
||||||
stream.remove_object_from_related_stores(boosted, stores=audience)
|
stream.remove_object_from_related_stores(boosted, stores=audience)
|
||||||
for status in old_versions:
|
for status in old_versions:
|
||||||
stream.remove_object_from_related_stores(status, stores=audience)
|
stream.remove_object_from_related_stores(status, stores=audience)
|
||||||
|
|
||||||
|
|
||||||
|
def get_status_type(status):
|
||||||
|
"""return status type even for boosted statuses"""
|
||||||
|
status_type = status.status_type.lower()
|
||||||
|
|
||||||
|
# Check if current status is a boost
|
||||||
|
if hasattr(status, "boost"):
|
||||||
|
# Act in accordance of your findings
|
||||||
|
if hasattr(status.boost.boosted_status, "review"):
|
||||||
|
status_type = "review"
|
||||||
|
if hasattr(status.boost.boosted_status, "comment"):
|
||||||
|
status_type = "comment"
|
||||||
|
if hasattr(status.boost.boosted_status, "quotation"):
|
||||||
|
status_type = "quotation"
|
||||||
|
|
||||||
|
return status_type
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import models
|
||||||
from bookwyrm.models.fields import ClearableFileInputWithWarning
|
from bookwyrm.models.fields import ClearableFileInputWithWarning
|
||||||
|
from bookwyrm.models.user import FeedFilterChoices
|
||||||
|
|
||||||
|
|
||||||
class CustomForm(ModelForm):
|
class CustomForm(ModelForm):
|
||||||
|
@ -196,6 +197,18 @@ class UserGroupForm(CustomForm):
|
||||||
fields = ["groups"]
|
fields = ["groups"]
|
||||||
|
|
||||||
|
|
||||||
|
class FeedStatusTypesForm(CustomForm):
|
||||||
|
class Meta:
|
||||||
|
model = models.User
|
||||||
|
fields = ["feed_status_types"]
|
||||||
|
help_texts = {f: None for f in fields}
|
||||||
|
widgets = {
|
||||||
|
"feed_status_types": widgets.CheckboxSelectMultiple(
|
||||||
|
choices=FeedFilterChoices,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class CoverForm(CustomForm):
|
class CoverForm(CustomForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Book
|
model = models.Book
|
||||||
|
|
32
bookwyrm/migrations/0119_user_feed_status_types.py
Normal file
32
bookwyrm/migrations/0119_user_feed_status_types.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Generated by Django 3.2.5 on 2021-11-24 10:15
|
||||||
|
|
||||||
|
import bookwyrm.models.user
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0118_alter_user_preferred_language"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="user",
|
||||||
|
name="feed_status_types",
|
||||||
|
field=django.contrib.postgres.fields.ArrayField(
|
||||||
|
base_field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("review", "Reviews"),
|
||||||
|
("comment", "Comments"),
|
||||||
|
("quotation", "Quotations"),
|
||||||
|
("everything", "Everything else"),
|
||||||
|
],
|
||||||
|
max_length=10,
|
||||||
|
),
|
||||||
|
default=bookwyrm.models.user.get_feed_filter_choices,
|
||||||
|
size=8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -4,11 +4,12 @@ from urllib.parse import urlparse
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib.auth.models import AbstractUser, Group
|
from django.contrib.auth.models import AbstractUser, Group
|
||||||
from django.contrib.postgres.fields import CICharField
|
from django.contrib.postgres.fields import ArrayField, CICharField
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from model_utils import FieldTracker
|
from model_utils import FieldTracker
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
@ -27,6 +28,19 @@ from .federated_server import FederatedServer
|
||||||
from . import fields, Review
|
from . import fields, Review
|
||||||
|
|
||||||
|
|
||||||
|
FeedFilterChoices = [
|
||||||
|
("review", _("Reviews")),
|
||||||
|
("comment", _("Comments")),
|
||||||
|
("quotation", _("Quotations")),
|
||||||
|
("everything", _("Everything else")),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_feed_filter_choices():
|
||||||
|
"""return a list of filter choice keys"""
|
||||||
|
return [f[0] for f in FeedFilterChoices]
|
||||||
|
|
||||||
|
|
||||||
def site_link():
|
def site_link():
|
||||||
"""helper for generating links to the site"""
|
"""helper for generating links to the site"""
|
||||||
protocol = "https" if USE_HTTPS else "http"
|
protocol = "https" if USE_HTTPS else "http"
|
||||||
|
@ -128,6 +142,13 @@ class User(OrderedCollectionPageMixin, AbstractUser):
|
||||||
show_suggested_users = models.BooleanField(default=True)
|
show_suggested_users = models.BooleanField(default=True)
|
||||||
discoverable = fields.BooleanField(default=False)
|
discoverable = fields.BooleanField(default=False)
|
||||||
|
|
||||||
|
# feed options
|
||||||
|
feed_status_types = ArrayField(
|
||||||
|
models.CharField(max_length=10, blank=False, choices=FeedFilterChoices),
|
||||||
|
size=8,
|
||||||
|
default=get_feed_filter_choices,
|
||||||
|
)
|
||||||
|
|
||||||
preferred_timezone = models.CharField(
|
preferred_timezone = models.CharField(
|
||||||
choices=[(str(tz), str(tz)) for tz in pytz.all_timezones],
|
choices=[(str(tz), str(tz)) for tz in pytz.all_timezones],
|
||||||
default=str(pytz.utc),
|
default=str(pytz.utc),
|
||||||
|
|
|
@ -45,6 +45,13 @@ let BookWyrm = new class {
|
||||||
'change',
|
'change',
|
||||||
this.disableIfTooLarge.bind(this)
|
this.disableIfTooLarge.bind(this)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-duplicate]')
|
||||||
|
.forEach(node => node.addEventListener(
|
||||||
|
'click',
|
||||||
|
this.duplicateInput.bind(this)
|
||||||
|
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,9 +120,44 @@ let BookWyrm = new class {
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
updateCountElement(counter, data) {
|
updateCountElement(counter, data) {
|
||||||
|
let count = data.count;
|
||||||
|
const count_by_type = data.count_by_type;
|
||||||
const currentCount = counter.innerText;
|
const currentCount = counter.innerText;
|
||||||
const count = data.count;
|
|
||||||
const hasMentions = data.has_mentions;
|
const hasMentions = data.has_mentions;
|
||||||
|
const allowedStatusTypesEl = document.getElementById('unread-notifications-wrapper');
|
||||||
|
|
||||||
|
// If we're on the right counter element
|
||||||
|
if (counter.closest('[data-poll-wrapper]').contains(allowedStatusTypesEl)) {
|
||||||
|
const allowedStatusTypes = JSON.parse(allowedStatusTypesEl.textContent);
|
||||||
|
|
||||||
|
// For keys in common between allowedStatusTypes and count_by_type
|
||||||
|
// This concerns 'review', 'quotation', 'comment'
|
||||||
|
count = allowedStatusTypes.reduce(function(prev, currentKey) {
|
||||||
|
const currentValue = count_by_type[currentKey] | 0;
|
||||||
|
|
||||||
|
return prev + currentValue;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
// Add all the "other" in count_by_type if 'everything' is allowed
|
||||||
|
if (allowedStatusTypes.includes('everything')) {
|
||||||
|
// Clone count_by_type with 0 for reviews/quotations/comments
|
||||||
|
const count_by_everything_else = Object.assign(
|
||||||
|
{},
|
||||||
|
count_by_type,
|
||||||
|
{review: 0, quotation: 0, comment: 0}
|
||||||
|
);
|
||||||
|
|
||||||
|
count = Object.keys(count_by_everything_else).reduce(
|
||||||
|
function(prev, currentKey) {
|
||||||
|
const currentValue =
|
||||||
|
count_by_everything_else[currentKey] | 0
|
||||||
|
|
||||||
|
return prev + currentValue;
|
||||||
|
},
|
||||||
|
count
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count != currentCount) {
|
if (count != currentCount) {
|
||||||
this.addRemoveClass(counter.closest('[data-poll-wrapper]'), 'is-hidden', count < 1);
|
this.addRemoveClass(counter.closest('[data-poll-wrapper]'), 'is-hidden', count < 1);
|
||||||
|
@ -368,4 +410,24 @@ let BookWyrm = new class {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
duplicateInput (event ) {
|
||||||
|
const trigger = event.currentTarget;
|
||||||
|
const input_id = trigger.dataset['duplicate']
|
||||||
|
const orig = document.getElementById(input_id);
|
||||||
|
const parent = orig.parentNode;
|
||||||
|
const new_count = parent.querySelectorAll("input").length + 1
|
||||||
|
|
||||||
|
let input = orig.cloneNode();
|
||||||
|
|
||||||
|
input.id += ("-" + (new_count))
|
||||||
|
input.value = ""
|
||||||
|
|
||||||
|
let label = parent.querySelector("label").cloneNode();
|
||||||
|
|
||||||
|
label.setAttribute("for", input.id)
|
||||||
|
|
||||||
|
parent.appendChild(label)
|
||||||
|
parent.appendChild(input)
|
||||||
|
}
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -187,6 +187,7 @@ let StatusCache = new class {
|
||||||
.forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", false));
|
.forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", false));
|
||||||
|
|
||||||
// Remove existing disabled states
|
// Remove existing disabled states
|
||||||
|
|
||||||
button.querySelectorAll("[data-shelf-dropdown-identifier] button")
|
button.querySelectorAll("[data-shelf-dropdown-identifier] button")
|
||||||
.forEach(item => item.disabled = false);
|
.forEach(item => item.disabled = false);
|
||||||
|
|
||||||
|
|
|
@ -153,12 +153,21 @@
|
||||||
|
|
||||||
{# user's relationship to the book #}
|
{# user's relationship to the book #}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
|
{% if user_shelfbooks.count > 0 %}
|
||||||
|
<h2 class="title is-5">
|
||||||
|
{% trans "You have shelved this edition in:" %}
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
{% for shelf in user_shelfbooks %}
|
{% for shelf in user_shelfbooks %}
|
||||||
<p>
|
<li class="box">
|
||||||
{% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}This edition is on your <a href="{{ path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %}
|
{% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}<a href="{{ path }}">{{ shelf_name }}</a>{% endblocktrans %}
|
||||||
{% include 'snippets/shelf_selector.html' with current=shelf.shelf %}
|
<div class="mb-3">
|
||||||
</p>
|
{% include 'snippets/shelf_selector.html' with shelf=shelf.shelf class="is-small" readthrough=readthrough %}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
{% for shelf in other_edition_shelves %}
|
{% for shelf in other_edition_shelves %}
|
||||||
<p>
|
<p>
|
||||||
{% blocktrans with book_path=shelf.book.local_path shelf_path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}A <a href="{{ book_path }}">different edition</a> of this book is on your <a href="{{ shelf_path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %}
|
{% blocktrans with book_path=shelf.book.local_path shelf_path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}A <a href="{{ book_path }}">different edition</a> of this book is on your <a href="{{ shelf_path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %}
|
||||||
|
|
|
@ -141,11 +141,15 @@
|
||||||
<label class="label" for="id_add_author">
|
<label class="label" for="id_add_author">
|
||||||
{% trans "Add Authors:" %}
|
{% trans "Add Authors:" %}
|
||||||
</label>
|
</label>
|
||||||
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'John Doe, Jane Smith' %}" value="{{ add_author }}" {% if confirm_mode %}readonly{% endif %} aria-describedby="desc_add_author">
|
{% for author in add_author %}
|
||||||
<span class="help" id="desc_add_author">
|
<label class="label is-sr-only" for="id_add_author{% if not forloop.first %}-{{forloop.counter}}{% endif %}">{% trans "Add Author" %}</label>
|
||||||
{% trans "Separate multiple values with commas." %}
|
<input class="input" type="text" name="add_author" id="id_add_author{% if not forloop.first %}-{{forloop.counter}}{% endif %}" placeholder="{% trans 'Jane Doe' %}" value="{{ author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||||
</span>
|
{% empty %}
|
||||||
|
<label class="label is-sr-only" for="id_add_author">{% trans "Add Author" %}</label>
|
||||||
|
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'Jane Doe' %}" value="{{ author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
<span class="help"><button class="button is-small" type="button" data-duplicate="id_add_author" id="another_author_field">{% trans "Add Another Author" %}</button></span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</p>
|
</p>
|
||||||
<form name="directory" method="POST" action="{% url 'directory' %}">
|
<form name="directory" method="POST" action="{% url 'directory' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="button is-primary" type="submit">Join Directory</button>
|
<button class="button is-primary" type="submit">{% trans "Join Directory" %}</button>
|
||||||
<p class="help">
|
<p class="help">
|
||||||
{% url 'prefs-profile' as path %}
|
{% url 'prefs-profile' as path %}
|
||||||
{% blocktrans with path=path %}You can opt-out at any time in your <a href="{{ path }}">profile settings.</a>{% endblocktrans %}
|
{% blocktrans with path=path %}You can opt-out at any time in your <a href="{{ path }}">profile settings.</a>{% endblocktrans %}
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<div class="column is-narrow">
|
<div class="column is-narrow">
|
||||||
{% trans "Dismiss message" as button_text %}
|
{% trans "Dismiss message" as button_text %}
|
||||||
<button type="button" class="delete set-display" data-id="hide_join_directory" data-value="true">
|
<button type="button" class="delete set-display" data-id="hide_join_directory" data-value="true">
|
||||||
<span>Dismiss message</span>
|
<span>{% trans "Dismiss message" %}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
|
@ -16,10 +16,45 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# feed settings #}
|
||||||
|
<details class="mb-5" {% if settings_saved %}open{% endif %}>
|
||||||
|
<summary>
|
||||||
|
<span class="has-text-weight-bold">
|
||||||
|
{{ _("Feed settings") }}
|
||||||
|
</span>
|
||||||
|
{% if settings_saved %}
|
||||||
|
<span class="tag is-success is-light ml-2">{{ _("Saved!") }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</summary>
|
||||||
|
<form class="level is-align-items-flex-end" method="post" action="/{{ tab.key }}#feed">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<label class="label mt-2 mb-1">Status types</label>
|
||||||
|
{% for name, value in feed_status_types_options %}
|
||||||
|
<label class="mr-2">
|
||||||
|
<input type="checkbox" name="feed_status_types" value="{{ name }}" {% if name in user.feed_status_types %}checked=""{% endif %}/>
|
||||||
|
{{ value }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-right control">
|
||||||
|
<button class="button is-small is-primary is-outlined" type="submit">
|
||||||
|
{{ _("Save settings") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</details>
|
||||||
|
|
||||||
{# announcements and system messages #}
|
{# announcements and system messages #}
|
||||||
{% if not activities.number > 1 %}
|
{% if not activities.number > 1 %}
|
||||||
<a href="{{ request.path }}" class="transition-y is-hidden notification is-primary is-block" data-poll-wrapper>
|
<a href="{{ request.path }}" class="transition-y is-hidden notification is-primary is-block" data-poll-wrapper>
|
||||||
{% blocktrans with tab_key=tab.key %}load <span data-poll="stream/{{ tab_key }}">0</span> unread status(es){% endblocktrans %}
|
{% blocktrans with tab_key=tab.key %}load <span data-poll="stream/{{ tab_key }}">0</span> unread status(es){% endblocktrans %}
|
||||||
|
{{ allowed_status_types|json_script:"unread-notifications-wrapper" }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{% if request.user.show_goal and not goal and tab.key == 'home' %}
|
{% if request.user.show_goal and not goal and tab.key == 'home' %}
|
||||||
|
@ -36,6 +71,7 @@
|
||||||
{% if not activities %}
|
{% if not activities %}
|
||||||
<div class="block content">
|
<div class="block content">
|
||||||
<p>{% trans "There aren't any activities right now! Try following a user to get started" %}</p>
|
<p>{% trans "There aren't any activities right now! Try following a user to get started" %}</p>
|
||||||
|
<p>{% if user.feed_status_types|length < 4 %}{% trans "Alternatively, you can try enabling more status types" %}{% endif %}</p>
|
||||||
|
|
||||||
{% if request.user.show_suggested_users and suggested_users %}
|
{% if request.user.show_suggested_users and suggested_users %}
|
||||||
{# suggested users for when things are very lonely #}
|
{# suggested users for when things are very lonely #}
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
|
|
||||||
<div class="select is-small mt-1 mb-3">
|
<div class="select is-small mt-1 mb-3">
|
||||||
<select name="{{ book.id }}" aria-label="{% blocktrans with book_title=book.title %}Have you read {{ book_title }}?{% endblocktrans %}">
|
<select name="{{ book.id }}" aria-label="{% blocktrans with book_title=book.title %}Have you read {{ book_title }}?{% endblocktrans %}">
|
||||||
<option disabled selected value>Add to your books</option>
|
<option disabled selected value>{% trans 'Add to your books' %}</option>
|
||||||
{% for shelf in user_shelves %}
|
{% for shelf in user_shelves %}
|
||||||
<option value="{{ shelf.id }}">{{ shelf.name }}</option>
|
<option value="{{ shelf.id }}">
|
||||||
|
{% if shelf.identifier == 'to-read' %}{% trans "To Read" %}
|
||||||
|
{% elif shelf.identifier == 'reading' %}{% trans "Currently Reading" %}
|
||||||
|
{% elif shelf.identifier == 'read' %}{% trans "Read" %}
|
||||||
|
{% else %}{{ shelf.name }}{% endif %}
|
||||||
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<header class="columns is-mobile">
|
<header class="columns is-mobile">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h3 class="title is-5">
|
<h3 class="title is-5">
|
||||||
Results from
|
{% trans 'Results from' %}
|
||||||
<a href="{{ result_set.connector.base_url }}" target="_blank">{{ result_set.connector.name|default:result_set.connector.identifier }}</a>
|
<a href="{{ result_set.connector.base_url }}" target="_blank">{{ result_set.connector.name|default:result_set.connector.identifier }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -80,7 +80,10 @@
|
||||||
<div class="block columns is-mobile">
|
<div class="block columns is-mobile">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h2 class="title is-3">
|
<h2 class="title is-3">
|
||||||
{{ shelf.name }}
|
{% if shelf.identifier == 'to-read' %}{% trans "To Read" %}
|
||||||
|
{% elif shelf.identifier == 'reading' %}{% trans "Currently Reading" %}
|
||||||
|
{% elif shelf.identifier == 'read' %}{% trans "Read" %}
|
||||||
|
{% else %}{{ shelf.name }}{% endif %}
|
||||||
<span class="subtitle">
|
<span class="subtitle">
|
||||||
{% include 'snippets/privacy-icons.html' with item=shelf %}
|
{% include 'snippets/privacy-icons.html' with item=shelf %}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -9,10 +9,11 @@ Finish "<em>{{ book_title }}</em>"
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-open %}
|
{% block modal-form-open %}
|
||||||
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post" class="submit-status">
|
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
||||||
<input type="hidden" name="reading_status" value="read">
|
<input type="hidden" name="reading_status" value="read">
|
||||||
|
<input type="hidden" name="shelf" value="{{ move_from }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block reading-dates %}
|
{% block reading-dates %}
|
||||||
|
|
|
@ -9,8 +9,9 @@ Start "<em>{{ book_title }}</em>"
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-open %}
|
{% block modal-form-open %}
|
||||||
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post" class="submit-status">
|
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
|
||||||
<input type="hidden" name="reading_status" value="reading">
|
<input type="hidden" name="reading_status" value="reading">
|
||||||
|
<input type="hidden" name="shelf" value="{{ move_from }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,9 @@ Want to Read "<em>{{ book_title }}</em>"
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-open %}
|
{% block modal-form-open %}
|
||||||
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post" class="submit-status">
|
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
|
||||||
<input type="hidden" name="reading_status" value="to-read">
|
<input type="hidden" name="reading_status" value="to-read">
|
||||||
|
<input type="hidden" name="shelf" value="{{ move_from }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,96 @@
|
||||||
{% extends 'components/dropdown.html' %}
|
{% extends 'components/dropdown.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load bookwyrm_tags %}
|
||||||
|
{% load utilities %}
|
||||||
|
|
||||||
{% block dropdown-trigger %}
|
{% block dropdown-trigger %}
|
||||||
<span>{% trans "Move book" %}</span>
|
<span>{% trans "Move book" %}</span>
|
||||||
<span class="icon icon-arrow-down" aria-hidden="true"></span>
|
<span class="icon icon-arrow-down" aria-hidden="true"></span>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block dropdown-list %}
|
{% block dropdown-list %}
|
||||||
|
{% with book.id|uuid as uuid %}
|
||||||
|
{% active_shelf book as active_shelf %}
|
||||||
|
{% latest_read_through book request.user as readthrough %}
|
||||||
|
|
||||||
{% for shelf in user_shelves %}
|
{% for shelf in user_shelves %}
|
||||||
|
|
||||||
|
{% if shelf.editable %}
|
||||||
<li role="menuitem" class="dropdown-item p-0">
|
<li role="menuitem" class="dropdown-item p-0">
|
||||||
<form name="shelve" action="/shelve/" method="post">
|
<form name="shelve" action="/shelve/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.id }}">
|
<input type="hidden" name="book" value="{{ book.id }}">
|
||||||
<input type="hidden" name="change-shelf-from" value="{{ current.identifier }}">
|
<input type="hidden" name="change-shelf-from" value="{{ current.identifier }}">
|
||||||
<input type="hidden" name="shelf" value="{{ shelf.identifier }}">
|
<input type="hidden" name="shelf" value="{{ shelf.identifier }}">
|
||||||
<button class="button is-fullwidth is-small shelf-option is-radiusless is-white" type="submit" {% if shelf.identifier == current.identifier %}disabled{% endif %}><span>{{ shelf.name }}</span></button>
|
|
||||||
|
<button class="button is-fullwidth is-small shelf-option is-radiusless is-white" type="submit" {% if shelf.identifier == current.identifier %}disabled{% endif %}>
|
||||||
|
<span>
|
||||||
|
{% if shelf.identifier == 'to-read' %}{% trans "To Read" %}
|
||||||
|
{% elif shelf.identifier == 'reading' %}{% trans "Currently Reading" %}
|
||||||
|
{% elif shelf.identifier == 'read' %}{% trans "Read" %}
|
||||||
|
{% else %}{{ shelf.name }}{% endif %}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
{% else%}
|
||||||
|
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
|
||||||
|
{% with button_class="is-fullwidth is-small shelf-option is-radiusless is-white" %}
|
||||||
|
<li role="menuitem" class="dropdown-item p-0">
|
||||||
|
{% if shelf.identifier == 'reading' %}
|
||||||
|
|
||||||
|
{% trans "Start reading" as button_text %}
|
||||||
|
{% url 'reading-status' 'start' book.id as fallback_url %}
|
||||||
|
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="start_reading" controls_uid=uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %}
|
||||||
|
|
||||||
|
|
||||||
|
{% elif shelf.identifier == 'read' %}
|
||||||
|
|
||||||
|
{% trans "Read" as button_text %}
|
||||||
|
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
||||||
|
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="finish_reading" controls_uid=uuid focus="modal_title_finish_reading" disabled=is_current fallback_url=fallback_url %}
|
||||||
|
|
||||||
|
{% elif shelf.identifier == 'to-read' %}
|
||||||
|
|
||||||
|
{% trans "Want to read" as button_text %}
|
||||||
|
{% url 'reading-status' 'want' book.id as fallback_url %}
|
||||||
|
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="want_to_read" controls_uid=uuid focus="modal_title_want_to_read" disabled=is_current fallback_url=fallback_url %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endwith %}
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="navbar-divider" role="separator"></li>
|
|
||||||
|
{% if shelf.identifier == 'all' %}
|
||||||
|
{% for shelved_in in book.shelves.all %}
|
||||||
|
<li class="navbar-divider m-0" role="separator" ></li>
|
||||||
<li role="menuitem" class="dropdown-item p-0">
|
<li role="menuitem" class="dropdown-item p-0">
|
||||||
<form name="shelve" action="/unshelve/" method="post">
|
<form name="shelve" action="/unshelve/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.id }}">
|
<input type="hidden" name="book" value="{{ book.id }}">
|
||||||
<input type="hidden" name="shelf" value="{{ current.id }}">
|
<input type="hidden" name="shelf" value="{{ shelved_in.id }}">
|
||||||
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove" %}</button>
|
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove from" %} {{ shelved_in.name }}</button>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<li class="navbar-divider" role="separator" ></li>
|
||||||
|
<li role="menuitem" class="dropdown-item p-0">
|
||||||
|
<form name="shelve" action="/unshelve/" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="book" value="{{ book.id }}">
|
||||||
|
<input type="hidden" name="shelf" value="{{ shelf.id }}">
|
||||||
|
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove from" %} {{ shelf.name }}</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid move_from=current.id refresh=True %}
|
||||||
|
|
||||||
|
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid move_from=current.id refresh=True %}
|
||||||
|
|
||||||
|
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid move_from=current.id readthrough=readthrough refresh=True %}
|
||||||
|
|
||||||
|
{% endwith %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
{% elif shelf.editable %}
|
{% elif shelf.editable %}
|
||||||
|
|
||||||
<form name="shelve" action="/shelve/" method="post">
|
<form name="shelve" action="/shelve/" method="post" autocomplete="off">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
|
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
|
||||||
<button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>
|
<button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% if fallback_url %}
|
{% if fallback_url %}
|
||||||
<form name="fallback_form_{{ 0|uuid }}" method="GET" action="{{ fallback_url }}">
|
<form name="fallback_form_{{ 0|uuid }}" method="GET" action="{{ fallback_url }}" autocomplete="off">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button
|
<button
|
||||||
{% if not fallback_url %}
|
{% if not fallback_url %}
|
||||||
|
|
|
@ -29,8 +29,13 @@
|
||||||
<div class="columns is-mobile scroll-x">
|
<div class="columns is-mobile scroll-x">
|
||||||
{% for shelf in shelves %}
|
{% for shelf in shelves %}
|
||||||
<div class="column is-narrow">
|
<div class="column is-narrow">
|
||||||
<h3>{{ shelf.name }}
|
<h3>
|
||||||
{% if shelf.size > 3 %}<small>(<a href="{{ shelf.local_path }}">{% blocktrans with size=shelf.size %}View all {{ size }}{% endblocktrans %}</a>)</small>{% endif %}</h3>
|
{% if shelf.name == 'To Read' %}{% trans "To Read" %}
|
||||||
|
{% elif shelf.name == 'Currently Reading' %}{% trans "Currently Reading" %}
|
||||||
|
{% elif shelf.name == 'Read' %}{% trans "Read" %}
|
||||||
|
{% else %}{{ shelf.name }}{% endif %}
|
||||||
|
{% if shelf.size > 3 %}<small>(<a href="{{ shelf.local_path }}">{% blocktrans with size=shelf.size %}View all {{ size }}{% endblocktrans %}</a>)</small>{% endif %}
|
||||||
|
</h3>
|
||||||
<div class="is-mobile field is-grouped">
|
<div class="is-mobile field is-grouped">
|
||||||
{% for book in shelf.books %}
|
{% for book in shelf.books %}
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
@ -49,7 +54,8 @@
|
||||||
|
|
||||||
{% if goal %}
|
{% if goal %}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<h2 class="title">{% now 'Y' %} Reading Goal</h2>
|
{% now 'Y' as current_year%}
|
||||||
|
<h2 class="title">{% blocktrans %}{{ current_year }} Reading Goal{% endblocktrans %}</h2>
|
||||||
{% include 'snippets/goal_progress.html' with goal=goal %}
|
{% include 'snippets/goal_progress.html' with goal=goal %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -77,7 +77,12 @@ def related_status(notification):
|
||||||
def active_shelf(context, book):
|
def active_shelf(context, book):
|
||||||
"""check what shelf a user has a book on, if any"""
|
"""check what shelf a user has a book on, if any"""
|
||||||
if hasattr(book, "current_shelves"):
|
if hasattr(book, "current_shelves"):
|
||||||
return book.current_shelves[0] if len(book.current_shelves) else {"book": book}
|
read_shelves = [
|
||||||
|
s
|
||||||
|
for s in book.current_shelves
|
||||||
|
if s.shelf.identifier in models.Shelf.READ_STATUS_IDENTIFIERS
|
||||||
|
]
|
||||||
|
return read_shelves[0] if len(read_shelves) else {"book": book}
|
||||||
|
|
||||||
shelf = (
|
shelf = (
|
||||||
models.ShelfBook.objects.filter(
|
models.ShelfBook.objects.filter(
|
||||||
|
|
|
@ -50,10 +50,17 @@ class UpdateViews(TestCase):
|
||||||
request = self.factory.get("")
|
request = self.factory.get("")
|
||||||
request.user = self.local_user
|
request.user = self.local_user
|
||||||
|
|
||||||
with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count") as mock:
|
with patch(
|
||||||
mock.return_value = 3
|
"bookwyrm.activitystreams.ActivityStream.get_unread_count"
|
||||||
result = views.get_unread_status_count(request, "home")
|
) as mock_count:
|
||||||
|
with patch(
|
||||||
|
"bookwyrm.activitystreams.ActivityStream.get_unread_count_by_status_type"
|
||||||
|
) as mock_count_by_status:
|
||||||
|
mock_count.return_value = 3
|
||||||
|
mock_count_by_status.return_value = {"review": 5}
|
||||||
|
result = views.get_unread_status_count(request, "home")
|
||||||
|
|
||||||
self.assertIsInstance(result, JsonResponse)
|
self.assertIsInstance(result, JsonResponse)
|
||||||
data = json.loads(result.getvalue())
|
data = json.loads(result.getvalue())
|
||||||
self.assertEqual(data["count"], 3)
|
self.assertEqual(data["count"], 3)
|
||||||
|
self.assertEqual(data["count_by_type"]["review"], 5)
|
||||||
|
|
|
@ -19,7 +19,7 @@ def request_isni_data(search_index, search_term, max_records=5):
|
||||||
"recordPacking": "xml",
|
"recordPacking": "xml",
|
||||||
"sortKeys": "RLV,pica,0,,",
|
"sortKeys": "RLV,pica,0,,",
|
||||||
}
|
}
|
||||||
result = requests.get("http://isni.oclc.org/sru/", params=query_params, timeout=10)
|
result = requests.get("http://isni.oclc.org/sru/", params=query_params, timeout=15)
|
||||||
# the OCLC ISNI server asserts the payload is encoded
|
# the OCLC ISNI server asserts the payload is encoded
|
||||||
# in latin1, but we know better
|
# in latin1, but we know better
|
||||||
result.encoding = "utf-8"
|
result.encoding = "utf-8"
|
||||||
|
|
|
@ -51,13 +51,14 @@ class EditBook(View):
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
return TemplateResponse(request, "book/edit/edit_book.html", data)
|
return TemplateResponse(request, "book/edit/edit_book.html", data)
|
||||||
|
|
||||||
add_author = request.POST.get("add_author")
|
# filter out empty author fields
|
||||||
# we're adding an author through a free text field
|
add_author = [author for author in request.POST.getlist("add_author") if author]
|
||||||
if add_author:
|
if add_author:
|
||||||
data["add_author"] = add_author
|
data["add_author"] = add_author
|
||||||
data["author_matches"] = []
|
data["author_matches"] = []
|
||||||
data["isni_matches"] = []
|
data["isni_matches"] = []
|
||||||
for author in add_author.split(","):
|
|
||||||
|
for author in add_author:
|
||||||
if not author:
|
if not author:
|
||||||
continue
|
continue
|
||||||
# check for existing authors
|
# check for existing authors
|
||||||
|
|
|
@ -10,10 +10,11 @@ from django.utils.decorators import method_decorator
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
|
||||||
from bookwyrm import activitystreams, forms, models
|
from bookwyrm import activitystreams, forms, models
|
||||||
|
from bookwyrm.models.user import FeedFilterChoices
|
||||||
from bookwyrm.activitypub import ActivitypubResponse
|
from bookwyrm.activitypub import ActivitypubResponse
|
||||||
from bookwyrm.settings import PAGE_LENGTH, STREAMS
|
from bookwyrm.settings import PAGE_LENGTH, STREAMS
|
||||||
from bookwyrm.suggested_users import suggested_users
|
from bookwyrm.suggested_users import suggested_users
|
||||||
from .helpers import get_user_from_username
|
from .helpers import filter_stream_by_status_type, get_user_from_username
|
||||||
from .helpers import is_api_request, is_bookwyrm_request
|
from .helpers import is_api_request, is_bookwyrm_request
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +23,17 @@ from .helpers import is_api_request, is_bookwyrm_request
|
||||||
class Feed(View):
|
class Feed(View):
|
||||||
"""activity stream"""
|
"""activity stream"""
|
||||||
|
|
||||||
def get(self, request, tab):
|
def post(self, request, tab):
|
||||||
|
"""save feed settings form, with a silent validation fail"""
|
||||||
|
settings_saved = False
|
||||||
|
form = forms.FeedStatusTypesForm(request.POST, instance=request.user)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
settings_saved = True
|
||||||
|
|
||||||
|
return self.get(request, tab, settings_saved)
|
||||||
|
|
||||||
|
def get(self, request, tab, settings_saved=False):
|
||||||
"""user's homepage with activity feed"""
|
"""user's homepage with activity feed"""
|
||||||
tab = [s for s in STREAMS if s["key"] == tab]
|
tab = [s for s in STREAMS if s["key"] == tab]
|
||||||
tab = tab[0] if tab else STREAMS[0]
|
tab = tab[0] if tab else STREAMS[0]
|
||||||
|
@ -30,7 +41,11 @@ class Feed(View):
|
||||||
activities = activitystreams.streams[tab["key"]].get_activity_stream(
|
activities = activitystreams.streams[tab["key"]].get_activity_stream(
|
||||||
request.user
|
request.user
|
||||||
)
|
)
|
||||||
paginated = Paginator(activities, PAGE_LENGTH)
|
filtered_activities = filter_stream_by_status_type(
|
||||||
|
activities,
|
||||||
|
allowed_types=request.user.feed_status_types,
|
||||||
|
)
|
||||||
|
paginated = Paginator(filtered_activities, PAGE_LENGTH)
|
||||||
|
|
||||||
suggestions = suggested_users.get_suggestions(request.user)
|
suggestions = suggested_users.get_suggestions(request.user)
|
||||||
|
|
||||||
|
@ -43,6 +58,9 @@ class Feed(View):
|
||||||
"tab": tab,
|
"tab": tab,
|
||||||
"streams": STREAMS,
|
"streams": STREAMS,
|
||||||
"goal_form": forms.GoalForm(),
|
"goal_form": forms.GoalForm(),
|
||||||
|
"feed_status_types_options": FeedFilterChoices,
|
||||||
|
"allowed_status_types": request.user.feed_status_types,
|
||||||
|
"settings_saved": settings_saved,
|
||||||
"path": f"/{tab['key']}",
|
"path": f"/{tab['key']}",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import dateutil.tz
|
||||||
from dateutil.parser import ParserError
|
from dateutil.parser import ParserError
|
||||||
|
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
|
from django.db.models import Q
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
|
||||||
|
@ -153,3 +154,29 @@ def set_language(user, response):
|
||||||
translation.activate(user.preferred_language)
|
translation.activate(user.preferred_language)
|
||||||
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user.preferred_language)
|
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user.preferred_language)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def filter_stream_by_status_type(activities, allowed_types=None):
|
||||||
|
"""filter out activities based on types"""
|
||||||
|
if not allowed_types:
|
||||||
|
allowed_types = []
|
||||||
|
|
||||||
|
if "review" not in allowed_types:
|
||||||
|
activities = activities.filter(
|
||||||
|
Q(review__isnull=True), Q(boost__boosted_status__review__isnull=True)
|
||||||
|
)
|
||||||
|
if "comment" not in allowed_types:
|
||||||
|
activities = activities.filter(
|
||||||
|
Q(comment__isnull=True), Q(boost__boosted_status__comment__isnull=True)
|
||||||
|
)
|
||||||
|
if "quotation" not in allowed_types:
|
||||||
|
activities = activities.filter(
|
||||||
|
Q(quotation__isnull=True), Q(boost__boosted_status__quotation__isnull=True)
|
||||||
|
)
|
||||||
|
if "everything" not in allowed_types:
|
||||||
|
activities = activities.filter(
|
||||||
|
Q(generatednote__isnull=True),
|
||||||
|
Q(boost__boosted_status__generatednote__isnull=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
return activities
|
||||||
|
|
|
@ -9,6 +9,7 @@ from django.views import View
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import models
|
||||||
|
from bookwyrm.views.shelf.shelf_actions import unshelve
|
||||||
from .status import CreateStatus
|
from .status import CreateStatus
|
||||||
from .helpers import get_edition, handle_reading_status, is_api_request
|
from .helpers import get_edition, handle_reading_status, is_api_request
|
||||||
from .helpers import load_date_in_user_tz_as_utc
|
from .helpers import load_date_in_user_tz_as_utc
|
||||||
|
@ -16,6 +17,7 @@ from .helpers import load_date_in_user_tz_as_utc
|
||||||
|
|
||||||
@method_decorator(login_required, name="dispatch")
|
@method_decorator(login_required, name="dispatch")
|
||||||
# pylint: disable=no-self-use
|
# pylint: disable=no-self-use
|
||||||
|
# pylint: disable=too-many-return-statements
|
||||||
class ReadingStatus(View):
|
class ReadingStatus(View):
|
||||||
"""consider reading a book"""
|
"""consider reading a book"""
|
||||||
|
|
||||||
|
@ -89,8 +91,21 @@ class ReadingStatus(View):
|
||||||
privacy = request.POST.get("privacy")
|
privacy = request.POST.get("privacy")
|
||||||
handle_reading_status(request.user, desired_shelf, book, privacy)
|
handle_reading_status(request.user, desired_shelf, book, privacy)
|
||||||
|
|
||||||
|
# if the request includes a "shelf" value we are using the 'move' button
|
||||||
|
if bool(request.POST.get("shelf")):
|
||||||
|
# unshelve the existing shelf
|
||||||
|
this_shelf = request.POST.get("shelf")
|
||||||
|
if (
|
||||||
|
bool(current_status_shelfbook)
|
||||||
|
and int(this_shelf) != int(current_status_shelfbook.shelf.id)
|
||||||
|
and current_status_shelfbook.shelf.identifier
|
||||||
|
!= desired_shelf.identifier
|
||||||
|
):
|
||||||
|
return unshelve(request, book_id=book_id)
|
||||||
|
|
||||||
if is_api_request(request):
|
if is_api_request(request):
|
||||||
return HttpResponse()
|
return HttpResponse()
|
||||||
|
|
||||||
return redirect(referer)
|
return redirect(referer)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,13 +91,13 @@ def shelve(request):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@require_POST
|
@require_POST
|
||||||
def unshelve(request):
|
def unshelve(request, book_id=False):
|
||||||
"""remove a book from a user's shelf"""
|
"""remove a book from a user's shelf"""
|
||||||
book = get_object_or_404(models.Edition, id=request.POST.get("book"))
|
identity = book_id if book_id else request.POST.get("book")
|
||||||
|
book = get_object_or_404(models.Edition, id=identity)
|
||||||
shelf_book = get_object_or_404(
|
shelf_book = get_object_or_404(
|
||||||
models.ShelfBook, book=book, shelf__id=request.POST["shelf"]
|
models.ShelfBook, book=book, shelf__id=request.POST["shelf"]
|
||||||
)
|
)
|
||||||
shelf_book.raise_not_deletable(request.user)
|
shelf_book.raise_not_deletable(request.user)
|
||||||
|
|
||||||
shelf_book.delete()
|
shelf_book.delete()
|
||||||
return redirect(request.headers.get("Referer", "/"))
|
return redirect(request.headers.get("Referer", "/"))
|
||||||
|
|
|
@ -54,6 +54,7 @@ class CreateStatus(View):
|
||||||
data = {"book": book}
|
data = {"book": book}
|
||||||
return TemplateResponse(request, "compose.html", data)
|
return TemplateResponse(request, "compose.html", data)
|
||||||
|
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
def post(self, request, status_type, existing_status_id=None):
|
def post(self, request, status_type, existing_status_id=None):
|
||||||
"""create status of whatever type"""
|
"""create status of whatever type"""
|
||||||
created = not existing_status_id
|
created = not existing_status_id
|
||||||
|
@ -117,11 +118,12 @@ class CreateStatus(View):
|
||||||
|
|
||||||
status.save(created=created)
|
status.save(created=created)
|
||||||
|
|
||||||
# update a readthorugh, if needed
|
# update a readthrough, if needed
|
||||||
try:
|
if bool(request.POST.get("id")):
|
||||||
edit_readthrough(request)
|
try:
|
||||||
except Http404:
|
edit_readthrough(request)
|
||||||
pass
|
except Http404:
|
||||||
|
pass
|
||||||
|
|
||||||
if is_api_request(request):
|
if is_api_request(request):
|
||||||
return HttpResponse()
|
return HttpResponse()
|
||||||
|
|
|
@ -22,4 +22,9 @@ def get_unread_status_count(request, stream="home"):
|
||||||
stream = activitystreams.streams.get(stream)
|
stream = activitystreams.streams.get(stream)
|
||||||
if not stream:
|
if not stream:
|
||||||
return JsonResponse({})
|
return JsonResponse({})
|
||||||
return JsonResponse({"count": stream.get_unread_count(request.user)})
|
return JsonResponse(
|
||||||
|
{
|
||||||
|
"count": stream.get_unread_count(request.user),
|
||||||
|
"count_by_type": stream.get_unread_count_by_status_type(request.user),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
1
bw-dev
1
bw-dev
|
@ -118,6 +118,7 @@ case "$CMD" in
|
||||||
git checkout l10n_main locale/pt_BR
|
git checkout l10n_main locale/pt_BR
|
||||||
git checkout l10n_main locale/zh_Hans
|
git checkout l10n_main locale/zh_Hans
|
||||||
git checkout l10n_main locale/zh_Hant
|
git checkout l10n_main locale/zh_Hant
|
||||||
|
runweb django-admin makemessages --no-wrap --ignore=venv -l en_US $@
|
||||||
runweb django-admin compilemessages --ignore venv
|
runweb django-admin compilemessages --ignore venv
|
||||||
;;
|
;;
|
||||||
build)
|
build)
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-17 18:03+0000\n"
|
"POT-Creation-Date: 2021-12-02 18:24+0000\n"
|
||||||
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: English <LL@li.org>\n"
|
"Language-Team: English <LL@li.org>\n"
|
||||||
|
@ -18,58 +18,58 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: bookwyrm/forms.py:248
|
#: bookwyrm/forms.py:262
|
||||||
msgid "A user with this email already exists."
|
msgid "A user with this email already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:262
|
#: bookwyrm/forms.py:276
|
||||||
msgid "One Day"
|
msgid "One Day"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:263
|
#: bookwyrm/forms.py:277
|
||||||
msgid "One Week"
|
msgid "One Week"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:264
|
#: bookwyrm/forms.py:278
|
||||||
msgid "One Month"
|
msgid "One Month"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:265
|
#: bookwyrm/forms.py:279
|
||||||
msgid "Does Not Expire"
|
msgid "Does Not Expire"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:269
|
#: bookwyrm/forms.py:283
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{i} uses"
|
msgid "{i} uses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:270
|
#: bookwyrm/forms.py:284
|
||||||
msgid "Unlimited"
|
msgid "Unlimited"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:338
|
#: bookwyrm/forms.py:352
|
||||||
msgid "List Order"
|
msgid "List Order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:339
|
#: bookwyrm/forms.py:353
|
||||||
msgid "Book Title"
|
msgid "Book Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:340 bookwyrm/templates/shelf/shelf.html:149
|
#: bookwyrm/forms.py:354 bookwyrm/templates/shelf/shelf.html:149
|
||||||
#: bookwyrm/templates/shelf/shelf.html:181
|
#: bookwyrm/templates/shelf/shelf.html:181
|
||||||
#: bookwyrm/templates/snippets/create_status/review.html:33
|
#: bookwyrm/templates/snippets/create_status/review.html:33
|
||||||
msgid "Rating"
|
msgid "Rating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:342 bookwyrm/templates/lists/list.html:110
|
#: bookwyrm/forms.py:356 bookwyrm/templates/lists/list.html:110
|
||||||
msgid "Sort By"
|
msgid "Sort By"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:346
|
#: bookwyrm/forms.py:360
|
||||||
msgid "Ascending"
|
msgid "Ascending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/forms.py:347
|
#: bookwyrm/forms.py:361
|
||||||
msgid "Descending"
|
msgid "Descending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -153,6 +153,22 @@ msgstr ""
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/models/user.py:32 bookwyrm/templates/book/book.html:218
|
||||||
|
msgid "Reviews"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/models/user.py:33
|
||||||
|
msgid "Comments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/models/user.py:34
|
||||||
|
msgid "Quotations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/models/user.py:35
|
||||||
|
msgid "Everything else"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:118
|
#: bookwyrm/settings.py:118
|
||||||
msgid "Home Timeline"
|
msgid "Home Timeline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -227,47 +243,51 @@ msgstr ""
|
||||||
msgid "Something went wrong! Sorry about that."
|
msgid "Something went wrong! Sorry about that."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:17
|
|
||||||
#: bookwyrm/templates/author/author.html:18
|
#: bookwyrm/templates/author/author.html:18
|
||||||
|
#: bookwyrm/templates/author/author.html:19
|
||||||
msgid "Edit Author"
|
msgid "Edit Author"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:34
|
#: bookwyrm/templates/author/author.html:35
|
||||||
#: bookwyrm/templates/author/edit_author.html:43
|
#: bookwyrm/templates/author/edit_author.html:43
|
||||||
msgid "Aliases:"
|
msgid "Aliases:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:45
|
#: bookwyrm/templates/author/author.html:46
|
||||||
msgid "Born:"
|
msgid "Born:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:52
|
#: bookwyrm/templates/author/author.html:53
|
||||||
msgid "Died:"
|
msgid "Died:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:61
|
#: bookwyrm/templates/author/author.html:62
|
||||||
msgid "Wikipedia"
|
msgid "Wikipedia"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:69
|
#: bookwyrm/templates/author/author.html:70
|
||||||
|
msgid "View ISNI record"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/author/author.html:78
|
||||||
#: bookwyrm/templates/book/book.html:94
|
#: bookwyrm/templates/book/book.html:94
|
||||||
msgid "View on OpenLibrary"
|
msgid "View on OpenLibrary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:77
|
#: bookwyrm/templates/author/author.html:86
|
||||||
#: bookwyrm/templates/book/book.html:97
|
#: bookwyrm/templates/book/book.html:97
|
||||||
msgid "View on Inventaire"
|
msgid "View on Inventaire"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:85
|
#: bookwyrm/templates/author/author.html:94
|
||||||
msgid "View on LibraryThing"
|
msgid "View on LibraryThing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:93
|
#: bookwyrm/templates/author/author.html:102
|
||||||
msgid "View on Goodreads"
|
msgid "View on Goodreads"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/author.html:108
|
#: bookwyrm/templates/author/author.html:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Books by %(name)s"
|
msgid "Books by %(name)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -277,17 +297,17 @@ msgid "Edit Author:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/edit_author.html:13
|
#: bookwyrm/templates/author/edit_author.html:13
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:18
|
#: bookwyrm/templates/book/edit/edit_book.html:19
|
||||||
msgid "Added:"
|
msgid "Added:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/edit_author.html:14
|
#: bookwyrm/templates/author/edit_author.html:14
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:21
|
#: bookwyrm/templates/book/edit/edit_book.html:22
|
||||||
msgid "Updated:"
|
msgid "Updated:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/edit_author.html:16
|
#: bookwyrm/templates/author/edit_author.html:16
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:25
|
#: bookwyrm/templates/book/edit/edit_book.html:26
|
||||||
msgid "Last edited by:"
|
msgid "Last edited by:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -347,7 +367,7 @@ msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/author/edit_author.html:118
|
#: bookwyrm/templates/author/edit_author.html:118
|
||||||
#: bookwyrm/templates/book/book.html:140
|
#: bookwyrm/templates/book/book.html:140
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:110
|
#: bookwyrm/templates/book/edit/edit_book.html:121
|
||||||
#: bookwyrm/templates/book/readthrough.html:76
|
#: bookwyrm/templates/book/readthrough.html:76
|
||||||
#: bookwyrm/templates/groups/form.html:24
|
#: bookwyrm/templates/groups/form.html:24
|
||||||
#: bookwyrm/templates/lists/bookmark_button.html:15
|
#: bookwyrm/templates/lists/bookmark_button.html:15
|
||||||
|
@ -366,8 +386,8 @@ msgstr ""
|
||||||
#: bookwyrm/templates/author/edit_author.html:119
|
#: bookwyrm/templates/author/edit_author.html:119
|
||||||
#: bookwyrm/templates/book/book.html:141 bookwyrm/templates/book/book.html:190
|
#: bookwyrm/templates/book/book.html:141 bookwyrm/templates/book/book.html:190
|
||||||
#: bookwyrm/templates/book/cover_modal.html:32
|
#: bookwyrm/templates/book/cover_modal.html:32
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:112
|
#: bookwyrm/templates/book/edit/edit_book.html:123
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:115
|
#: bookwyrm/templates/book/edit/edit_book.html:126
|
||||||
#: bookwyrm/templates/book/readthrough.html:77
|
#: bookwyrm/templates/book/readthrough.html:77
|
||||||
#: bookwyrm/templates/groups/delete_group_modal.html:17
|
#: bookwyrm/templates/groups/delete_group_modal.html:17
|
||||||
#: bookwyrm/templates/lists/delete_list_modal.html:17
|
#: bookwyrm/templates/lists/delete_list_modal.html:17
|
||||||
|
@ -445,10 +465,6 @@ msgstr ""
|
||||||
msgid "You don't have any reading activity for this book."
|
msgid "You don't have any reading activity for this book."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:218
|
|
||||||
msgid "Reviews"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: bookwyrm/templates/book/book.html:223
|
#: bookwyrm/templates/book/book.html:223
|
||||||
msgid "Your reviews"
|
msgid "Your reviews"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -513,56 +529,60 @@ msgstr ""
|
||||||
msgid "Load cover from url:"
|
msgid "Load cover from url:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:5
|
#: bookwyrm/templates/book/edit/edit_book.html:6
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:11
|
#: bookwyrm/templates/book/edit/edit_book.html:12
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Edit \"%(book_title)s\""
|
msgid "Edit \"%(book_title)s\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:5
|
#: bookwyrm/templates/book/edit/edit_book.html:6
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:13
|
#: bookwyrm/templates/book/edit/edit_book.html:14
|
||||||
msgid "Add Book"
|
msgid "Add Book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:47
|
#: bookwyrm/templates/book/edit/edit_book.html:48
|
||||||
msgid "Confirm Book Info"
|
msgid "Confirm Book Info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:55
|
#: bookwyrm/templates/book/edit/edit_book.html:56
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Is \"%(name)s\" an existing author?"
|
msgid "Is \"%(name)s\" one of these authors?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:64
|
#: bookwyrm/templates/book/edit/edit_book.html:67
|
||||||
#, python-format
|
#: bookwyrm/templates/book/edit/edit_book.html:69
|
||||||
msgid "Author of <em>%(book_title)s</em>"
|
msgid "Author of "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:68
|
#: bookwyrm/templates/book/edit/edit_book.html:69
|
||||||
|
msgid "Find more information at isni.org"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/book/edit/edit_book.html:79
|
||||||
msgid "This is a new author"
|
msgid "This is a new author"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:75
|
#: bookwyrm/templates/book/edit/edit_book.html:86
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Creating a new author: %(name)s"
|
msgid "Creating a new author: %(name)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:82
|
#: bookwyrm/templates/book/edit/edit_book.html:93
|
||||||
msgid "Is this an edition of an existing work?"
|
msgid "Is this an edition of an existing work?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:90
|
#: bookwyrm/templates/book/edit/edit_book.html:101
|
||||||
msgid "This is a new work"
|
msgid "This is a new work"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:97
|
#: bookwyrm/templates/book/edit/edit_book.html:108
|
||||||
#: bookwyrm/templates/groups/members.html:16
|
#: bookwyrm/templates/groups/members.html:16
|
||||||
#: bookwyrm/templates/landing/password_reset.html:30
|
#: bookwyrm/templates/landing/password_reset.html:30
|
||||||
#: bookwyrm/templates/snippets/remove_from_group_button.html:16
|
#: bookwyrm/templates/snippets/remove_from_group_button.html:16
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book.html:99
|
#: bookwyrm/templates/book/edit/edit_book.html:110
|
||||||
#: bookwyrm/templates/feed/status.html:9
|
#: bookwyrm/templates/feed/status.html:9
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1016,6 +1036,22 @@ msgstr ""
|
||||||
msgid "Learn more about %(site_name)s:"
|
msgid "Learn more about %(site_name)s:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/email/moderation_report/html_content.html:6
|
||||||
|
#: bookwyrm/templates/email/moderation_report/text_content.html:5
|
||||||
|
#, python-format
|
||||||
|
msgid "@%(reporter)s has flagged behavior by @%(reportee)s for moderation. "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/email/moderation_report/html_content.html:9
|
||||||
|
#: bookwyrm/templates/email/moderation_report/text_content.html:7
|
||||||
|
msgid "View report"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/email/moderation_report/subject.html:2
|
||||||
|
#, python-format
|
||||||
|
msgid "New report for %(site_name)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/email/password_reset/html_content.html:6
|
#: bookwyrm/templates/email/password_reset/html_content.html:6
|
||||||
#: bookwyrm/templates/email/password_reset/text_content.html:4
|
#: bookwyrm/templates/email/password_reset/text_content.html:4
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -1058,15 +1094,31 @@ msgstr ""
|
||||||
msgid "You have no messages right now."
|
msgid "You have no messages right now."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/feed/feed.html:22
|
#: bookwyrm/templates/feed/feed.html:23
|
||||||
|
msgid "Feed settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/feed/feed.html:26
|
||||||
|
msgid "Saved!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/feed/feed.html:47
|
||||||
|
msgid "Save settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/feed/feed.html:56
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "load <span data-poll=\"stream/%(tab_key)s\">0</span> unread status(es)"
|
msgid "load <span data-poll=\"stream/%(tab_key)s\">0</span> unread status(es)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/feed/feed.html:38
|
#: bookwyrm/templates/feed/feed.html:72
|
||||||
msgid "There aren't any activities right now! Try following a user to get started"
|
msgid "There aren't any activities right now! Try following a user to get started"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: bookwyrm/templates/feed/feed.html:73
|
||||||
|
msgid "Alternatively, you can try enabling more status types"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/feed/goal_card.html:6
|
#: bookwyrm/templates/feed/goal_card.html:6
|
||||||
#: bookwyrm/templates/feed/layout.html:90
|
#: bookwyrm/templates/feed/layout.html:90
|
||||||
#: bookwyrm/templates/user/goal_form.html:6
|
#: bookwyrm/templates/user/goal_form.html:6
|
||||||
|
@ -3842,7 +3894,7 @@ msgstr ""
|
||||||
msgid "File exceeds maximum size: 10MB"
|
msgid "File exceeds maximum size: 10MB"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templatetags/utilities.py:31
|
#: bookwyrm/templatetags/utilities.py:34
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(title)s: %(subtitle)s"
|
msgid "%(title)s: %(subtitle)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
||||||
"Project-Id-Version: bookwyrm\n"
|
"Project-Id-Version: bookwyrm\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-17 18:03+0000\n"
|
"POT-Creation-Date: 2021-11-17 18:03+0000\n"
|
||||||
"PO-Revision-Date: 2021-11-22 08:50\n"
|
"PO-Revision-Date: 2021-11-29 13:53\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: Lithuanian\n"
|
"Language-Team: Lithuanian\n"
|
||||||
"Language: lt\n"
|
"Language: lt\n"
|
||||||
|
@ -591,7 +591,7 @@ msgstr "Kalbos:"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book_form.html:74
|
#: bookwyrm/templates/book/edit/edit_book_form.html:74
|
||||||
msgid "Publication"
|
msgid "Publication"
|
||||||
msgstr "Paskelbimas"
|
msgstr "Leidimas"
|
||||||
|
|
||||||
#: bookwyrm/templates/book/edit/edit_book_form.html:77
|
#: bookwyrm/templates/book/edit/edit_book_form.html:77
|
||||||
msgid "Publisher:"
|
msgid "Publisher:"
|
||||||
|
@ -930,7 +930,7 @@ msgstr "<a href=\"%(user_path)s\">%(username)s</a> įvertino <a href=\"%(book_pa
|
||||||
#: bookwyrm/templates/discover/card-header.html:27
|
#: bookwyrm/templates/discover/card-header.html:27
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(user_path)s\">%(username)s</a> reviewed <a href=\"%(book_path)s\">%(book_title)s</a>"
|
msgid "<a href=\"%(user_path)s\">%(username)s</a> reviewed <a href=\"%(book_path)s\">%(book_title)s</a>"
|
||||||
msgstr "<a href=\"%(user_path)s\">%(username)s</a> peržiūrėjo <a href=\"%(book_path)s\">%(book_title)s</a>"
|
msgstr "<a href=\"%(user_path)s\">%(username)s</a> apžvelgė <a href=\"%(book_path)s\">%(book_title)s</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/discover/card-header.html:31
|
#: bookwyrm/templates/discover/card-header.html:31
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -1114,7 +1114,7 @@ msgstr "Šiuo metu skaitoma"
|
||||||
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12
|
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12
|
||||||
#: bookwyrm/templates/user/books_header.html:8
|
#: bookwyrm/templates/user/books_header.html:8
|
||||||
msgid "Read"
|
msgid "Read"
|
||||||
msgstr "Perskaičiau"
|
msgstr "Perskaityta"
|
||||||
|
|
||||||
#: bookwyrm/templates/feed/suggested_users.html:5
|
#: bookwyrm/templates/feed/suggested_users.html:5
|
||||||
#: bookwyrm/templates/get_started/users.html:6
|
#: bookwyrm/templates/get_started/users.html:6
|
||||||
|
@ -1483,7 +1483,7 @@ msgstr "Lentyna"
|
||||||
#: bookwyrm/templates/import/manual_review.html:13
|
#: bookwyrm/templates/import/manual_review.html:13
|
||||||
#: bookwyrm/templates/snippets/create_status.html:17
|
#: bookwyrm/templates/snippets/create_status.html:17
|
||||||
msgid "Review"
|
msgid "Review"
|
||||||
msgstr "Peržiūra"
|
msgstr "Apžvalga"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:119
|
#: bookwyrm/templates/import/import_status.html:119
|
||||||
msgid "Book"
|
msgid "Book"
|
||||||
|
@ -1513,7 +1513,7 @@ msgstr "Importuota"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:182
|
#: bookwyrm/templates/import/import_status.html:182
|
||||||
msgid "Needs manual review"
|
msgid "Needs manual review"
|
||||||
msgstr "Reikalingas manualus atsiliepimas"
|
msgstr "Reikalinga peržvelgti"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:195
|
#: bookwyrm/templates/import/import_status.html:195
|
||||||
msgid "Retry"
|
msgid "Retry"
|
||||||
|
@ -2416,7 +2416,7 @@ msgstr[3] "%(display_count)s prašymai pakviesti"
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/dashboard/dashboard.html:65
|
#: bookwyrm/templates/settings/dashboard/dashboard.html:65
|
||||||
msgid "Instance Activity"
|
msgid "Instance Activity"
|
||||||
msgstr "Pavyzdinė veikla"
|
msgstr "Serverio statistika"
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/dashboard/dashboard.html:83
|
#: bookwyrm/templates/settings/dashboard/dashboard.html:83
|
||||||
msgid "Interval:"
|
msgid "Interval:"
|
||||||
|
@ -2436,7 +2436,7 @@ msgstr "Naudotojo prisijungimo veikla"
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/dashboard/dashboard.html:112
|
#: bookwyrm/templates/settings/dashboard/dashboard.html:112
|
||||||
msgid "Status activity"
|
msgid "Status activity"
|
||||||
msgstr "Būsenos veikla"
|
msgstr "Būsenos"
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/dashboard/dashboard.html:118
|
#: bookwyrm/templates/settings/dashboard/dashboard.html:118
|
||||||
msgid "Works created"
|
msgid "Works created"
|
||||||
|
@ -3467,7 +3467,7 @@ msgstr "%(percent)s%% baigta!"
|
||||||
#: bookwyrm/templates/snippets/goal_progress.html:12
|
#: bookwyrm/templates/snippets/goal_progress.html:12
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You've read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
msgid "You've read <a href=\"%(path)s\">%(read_count)s of %(goal_count)s books</a>."
|
||||||
msgstr "Perskaitėte <a href=\"%(path)s\">%(read_count)s iš %(goal_count)s knygų</a>."
|
msgstr "Perskaityta <a href=\"%(path)s\">%(read_count)s iš %(goal_count)s knygų</a>."
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/goal_progress.html:14
|
#: bookwyrm/templates/snippets/goal_progress.html:14
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -3504,7 +3504,7 @@ msgstr "Viešas"
|
||||||
#: bookwyrm/templates/snippets/privacy_select.html:14
|
#: bookwyrm/templates/snippets/privacy_select.html:14
|
||||||
#: bookwyrm/templates/snippets/privacy_select_no_followers.html:14
|
#: bookwyrm/templates/snippets/privacy_select_no_followers.html:14
|
||||||
msgid "Unlisted"
|
msgid "Unlisted"
|
||||||
msgstr "Nėra sąraše"
|
msgstr "Slaptas"
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:12
|
#: bookwyrm/templates/snippets/privacy-icons.html:12
|
||||||
msgid "Followers-only"
|
msgid "Followers-only"
|
||||||
|
@ -3873,7 +3873,7 @@ msgstr[3] "%(mutuals_display)s sekėjai, kuriuos sekate jūs"
|
||||||
|
|
||||||
#: bookwyrm/templates/user/user_preview.html:38
|
#: bookwyrm/templates/user/user_preview.html:38
|
||||||
msgid "No followers you follow"
|
msgid "No followers you follow"
|
||||||
msgstr "Jūs nieko nesekate"
|
msgstr "Jūs kartu nieko nesekate"
|
||||||
|
|
||||||
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28
|
#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28
|
||||||
msgid "File exceeds maximum size: 10MB"
|
msgid "File exceeds maximum size: 10MB"
|
||||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
||||||
"Project-Id-Version: bookwyrm\n"
|
"Project-Id-Version: bookwyrm\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-17 18:03+0000\n"
|
"POT-Creation-Date: 2021-11-17 18:03+0000\n"
|
||||||
"PO-Revision-Date: 2021-11-17 18:42\n"
|
"PO-Revision-Date: 2021-11-29 09:31\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: Chinese Simplified\n"
|
"Language-Team: Chinese Simplified\n"
|
||||||
"Language: zh\n"
|
"Language: zh\n"
|
||||||
|
@ -184,7 +184,7 @@ msgstr "Español(西班牙语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:168
|
#: bookwyrm/settings.py:168
|
||||||
msgid "Galego (Galician)"
|
msgid "Galego (Galician)"
|
||||||
msgstr ""
|
msgstr "Galego(加利西亚语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:169
|
#: bookwyrm/settings.py:169
|
||||||
msgid "Français (French)"
|
msgid "Français (French)"
|
||||||
|
@ -192,11 +192,11 @@ msgstr "Français(法语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:170
|
#: bookwyrm/settings.py:170
|
||||||
msgid "Lietuvių (Lithuanian)"
|
msgid "Lietuvių (Lithuanian)"
|
||||||
msgstr ""
|
msgstr "Lietuvių(立陶宛语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:171
|
#: bookwyrm/settings.py:171
|
||||||
msgid "Português - Brasil (Brazilian Portuguese)"
|
msgid "Português - Brasil (Brazilian Portuguese)"
|
||||||
msgstr "葡萄牙语-巴西(巴西的葡语)"
|
msgstr "Português - Brasil(巴西葡萄牙语)"
|
||||||
|
|
||||||
#: bookwyrm/settings.py:172
|
#: bookwyrm/settings.py:172
|
||||||
msgid "简体中文 (Simplified Chinese)"
|
msgid "简体中文 (Simplified Chinese)"
|
||||||
|
@ -906,12 +906,12 @@ msgstr "<a href=\"%(user_path)s\">%(username)s</a> 想要阅读 <a href=\"%(book
|
||||||
#: bookwyrm/templates/discover/card-header.html:13
|
#: bookwyrm/templates/discover/card-header.html:13
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(user_path)s\">%(username)s</a> finished reading <a href=\"%(book_path)s\">%(book_title)s</a>"
|
msgid "<a href=\"%(user_path)s\">%(username)s</a> finished reading <a href=\"%(book_path)s\">%(book_title)s</a>"
|
||||||
msgstr ""
|
msgstr "<a href=\"%(user_path)s\">%(username)s</a> 完成了 <a href=\"%(book_path)s\">%(book_title)s</a> 的阅读"
|
||||||
|
|
||||||
#: bookwyrm/templates/discover/card-header.html:18
|
#: bookwyrm/templates/discover/card-header.html:18
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<a href=\"%(user_path)s\">%(username)s</a> started reading <a href=\"%(book_path)s\">%(book_title)s</a>"
|
msgid "<a href=\"%(user_path)s\">%(username)s</a> started reading <a href=\"%(book_path)s\">%(book_title)s</a>"
|
||||||
msgstr ""
|
msgstr "<a href=\"%(user_path)s\">%(username)s</a> 开始阅读 <a href=\"%(book_path)s\">%(book_title)s</a>"
|
||||||
|
|
||||||
#: bookwyrm/templates/discover/card-header.html:23
|
#: bookwyrm/templates/discover/card-header.html:23
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -1395,11 +1395,11 @@ msgstr "导入状态"
|
||||||
#: bookwyrm/templates/import/import_status.html:13
|
#: bookwyrm/templates/import/import_status.html:13
|
||||||
#: bookwyrm/templates/import/import_status.html:27
|
#: bookwyrm/templates/import/import_status.html:27
|
||||||
msgid "Retry Status"
|
msgid "Retry Status"
|
||||||
msgstr ""
|
msgstr "重试状态"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:22
|
#: bookwyrm/templates/import/import_status.html:22
|
||||||
msgid "Imports"
|
msgid "Imports"
|
||||||
msgstr ""
|
msgstr "导入"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:39
|
#: bookwyrm/templates/import/import_status.html:39
|
||||||
msgid "Import started:"
|
msgid "Import started:"
|
||||||
|
@ -1407,36 +1407,36 @@ msgstr "导入开始:"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:48
|
#: bookwyrm/templates/import/import_status.html:48
|
||||||
msgid "In progress"
|
msgid "In progress"
|
||||||
msgstr ""
|
msgstr "正在进行"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:50
|
#: bookwyrm/templates/import/import_status.html:50
|
||||||
msgid "Refresh"
|
msgid "Refresh"
|
||||||
msgstr ""
|
msgstr "刷新"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:71
|
#: bookwyrm/templates/import/import_status.html:71
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(display_counter)s item needs manual approval."
|
msgid "%(display_counter)s item needs manual approval."
|
||||||
msgid_plural "%(display_counter)s items need manual approval."
|
msgid_plural "%(display_counter)s items need manual approval."
|
||||||
msgstr[0] ""
|
msgstr[0] "%(display_counter)s 项需要手动批准。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:76
|
#: bookwyrm/templates/import/import_status.html:76
|
||||||
#: bookwyrm/templates/import/manual_review.html:8
|
#: bookwyrm/templates/import/manual_review.html:8
|
||||||
msgid "Review items"
|
msgid "Review items"
|
||||||
msgstr ""
|
msgstr "审阅项目"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:82
|
#: bookwyrm/templates/import/import_status.html:82
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(display_counter)s item failed to import."
|
msgid "%(display_counter)s item failed to import."
|
||||||
msgid_plural "%(display_counter)s items failed to import."
|
msgid_plural "%(display_counter)s items failed to import."
|
||||||
msgstr[0] ""
|
msgstr[0] "%(display_counter)s 项导入失败。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:88
|
#: bookwyrm/templates/import/import_status.html:88
|
||||||
msgid "View and troubleshoot failed items"
|
msgid "View and troubleshoot failed items"
|
||||||
msgstr ""
|
msgstr "查看并排查失败项目"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:100
|
#: bookwyrm/templates/import/import_status.html:100
|
||||||
msgid "Row"
|
msgid "Row"
|
||||||
msgstr ""
|
msgstr "行"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:103
|
#: bookwyrm/templates/import/import_status.html:103
|
||||||
#: bookwyrm/templates/shelf/shelf.html:141
|
#: bookwyrm/templates/shelf/shelf.html:141
|
||||||
|
@ -1446,7 +1446,7 @@ msgstr "标题"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:106
|
#: bookwyrm/templates/import/import_status.html:106
|
||||||
msgid "ISBN"
|
msgid "ISBN"
|
||||||
msgstr ""
|
msgstr "ISBN"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:109
|
#: bookwyrm/templates/import/import_status.html:109
|
||||||
#: bookwyrm/templates/shelf/shelf.html:142
|
#: bookwyrm/templates/shelf/shelf.html:142
|
||||||
|
@ -1456,7 +1456,7 @@ msgstr "作者"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:112
|
#: bookwyrm/templates/import/import_status.html:112
|
||||||
msgid "Shelf"
|
msgid "Shelf"
|
||||||
msgstr ""
|
msgstr "书架"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:115
|
#: bookwyrm/templates/import/import_status.html:115
|
||||||
#: bookwyrm/templates/import/manual_review.html:13
|
#: bookwyrm/templates/import/manual_review.html:13
|
||||||
|
@ -1480,11 +1480,11 @@ msgstr "状态"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:130
|
#: bookwyrm/templates/import/import_status.html:130
|
||||||
msgid "Import preview unavailable."
|
msgid "Import preview unavailable."
|
||||||
msgstr ""
|
msgstr "导入预览不可用。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:162
|
#: bookwyrm/templates/import/import_status.html:162
|
||||||
msgid "View imported review"
|
msgid "View imported review"
|
||||||
msgstr ""
|
msgstr "查看已导入的书评"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:176
|
#: bookwyrm/templates/import/import_status.html:176
|
||||||
msgid "Imported"
|
msgid "Imported"
|
||||||
|
@ -1492,28 +1492,28 @@ msgstr "已导入"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:182
|
#: bookwyrm/templates/import/import_status.html:182
|
||||||
msgid "Needs manual review"
|
msgid "Needs manual review"
|
||||||
msgstr ""
|
msgstr "需要手动批准"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:195
|
#: bookwyrm/templates/import/import_status.html:195
|
||||||
msgid "Retry"
|
msgid "Retry"
|
||||||
msgstr ""
|
msgstr "重试"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:213
|
#: bookwyrm/templates/import/import_status.html:213
|
||||||
msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format."
|
msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format."
|
||||||
msgstr ""
|
msgstr "此导入所用格式已不再受支持。 如果您想要在此次导入中排查缺失的项目,请点击下面的按钮来更新导入格式。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/import_status.html:215
|
#: bookwyrm/templates/import/import_status.html:215
|
||||||
msgid "Update import"
|
msgid "Update import"
|
||||||
msgstr ""
|
msgstr "更新导入"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/manual_review.html:5
|
#: bookwyrm/templates/import/manual_review.html:5
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:4
|
#: bookwyrm/templates/import/troubleshoot.html:4
|
||||||
msgid "Import Troubleshooting"
|
msgid "Import Troubleshooting"
|
||||||
msgstr ""
|
msgstr "导入排查"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/manual_review.html:21
|
#: bookwyrm/templates/import/manual_review.html:21
|
||||||
msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book."
|
msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book."
|
||||||
msgstr ""
|
msgstr "批准建议后,被提议的书将会永久添加到您的书架上并与您的阅读日期、书评、评分联系起来。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/manual_review.html:58
|
#: bookwyrm/templates/import/manual_review.html:58
|
||||||
#: bookwyrm/templates/lists/curate.html:57
|
#: bookwyrm/templates/lists/curate.html:57
|
||||||
|
@ -1522,7 +1522,7 @@ msgstr "批准"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/manual_review.html:66
|
#: bookwyrm/templates/import/manual_review.html:66
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr ""
|
msgstr "驳回"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/tooltip.html:6
|
#: bookwyrm/templates/import/tooltip.html:6
|
||||||
msgid "You can download your Goodreads data from the <a href=\"https://www.goodreads.com/review/import\" target=\"_blank\" rel=\"noopener\">Import/Export page</a> of your Goodreads account."
|
msgid "You can download your Goodreads data from the <a href=\"https://www.goodreads.com/review/import\" target=\"_blank\" rel=\"noopener\">Import/Export page</a> of your Goodreads account."
|
||||||
|
@ -1530,31 +1530,31 @@ msgstr "您可以从 <a href=\"https://www.goodreads.com/review/import\" target=
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:7
|
#: bookwyrm/templates/import/troubleshoot.html:7
|
||||||
msgid "Failed items"
|
msgid "Failed items"
|
||||||
msgstr ""
|
msgstr "失败项目"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:12
|
#: bookwyrm/templates/import/troubleshoot.html:12
|
||||||
msgid "Troubleshooting"
|
msgid "Troubleshooting"
|
||||||
msgstr ""
|
msgstr "问题排查"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:20
|
#: bookwyrm/templates/import/troubleshoot.html:20
|
||||||
msgid "Re-trying an import can fix missing items in cases such as:"
|
msgid "Re-trying an import can fix missing items in cases such as:"
|
||||||
msgstr ""
|
msgstr "重试导入可以修复以下情况的缺失项目:"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:23
|
#: bookwyrm/templates/import/troubleshoot.html:23
|
||||||
msgid "The book has been added to the instance since this import"
|
msgid "The book has been added to the instance since this import"
|
||||||
msgstr ""
|
msgstr "在此次导入后该书已被添加到本实例"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:24
|
#: bookwyrm/templates/import/troubleshoot.html:24
|
||||||
msgid "A transient error or timeout caused the external data source to be unavailable."
|
msgid "A transient error or timeout caused the external data source to be unavailable."
|
||||||
msgstr ""
|
msgstr "暂时的错误或超时导致外部数据源不可用。"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:25
|
#: bookwyrm/templates/import/troubleshoot.html:25
|
||||||
msgid "BookWyrm has been updated since this import with a bug fix"
|
msgid "BookWyrm has been updated since this import with a bug fix"
|
||||||
msgstr ""
|
msgstr "在此次导入后,BookWyrm 已经更新并修复了漏洞"
|
||||||
|
|
||||||
#: bookwyrm/templates/import/troubleshoot.html:28
|
#: bookwyrm/templates/import/troubleshoot.html:28
|
||||||
msgid "Contact your admin or <a href='https://github.com/bookwyrm-social/bookwyrm/issues'>open an issue</a> if you are seeing unexpected failed items."
|
msgid "Contact your admin or <a href='https://github.com/bookwyrm-social/bookwyrm/issues'>open an issue</a> if you are seeing unexpected failed items."
|
||||||
msgstr ""
|
msgstr "如果您看到意外失败的项目,请联系您的管理员或 <a href='https://github.com/bookwyrm-social/bookwyrm/issues'>发起一个 issue</a>。"
|
||||||
|
|
||||||
#: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230
|
#: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230
|
||||||
#, python-format
|
#, python-format
|
||||||
|
|
Loading…
Reference in a new issue