diff --git a/.env.example b/.env.example index fb0f7308d..1bf6d5406 100644 --- a/.env.example +++ b/.env.example @@ -137,3 +137,10 @@ TWO_FACTOR_LOGIN_MAX_SECONDS=60 # and AWS_S3_CUSTOM_DOMAIN (if used) are added by default. # Value should be a comma-separated list of host names. CSP_ADDITIONAL_HOSTS= + +# Time before being logged out (in seconds) +# SESSION_COOKIE_AGE=2592000 # current default: 30 days + +# Maximum allowed memory for file uploads (increase if users are having trouble +# uploading BookWyrm export files). +# DATA_UPLOAD_MAX_MEMORY_MiB=100 diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml deleted file mode 100644 index 4e7be4af3..000000000 --- a/.github/workflows/black.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Python Formatting (run ./bw-dev black to fix) - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - - uses: psf/black@22.12.0 - with: - version: 22.12.0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 68bb05d7e..51316ef62 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/curlylint.yaml b/.github/workflows/curlylint.yaml index 8d5c6b4f7..10ad04ce1 100644 --- a/.github/workflows/curlylint.yaml +++ b/.github/workflows/curlylint.yaml @@ -10,7 +10,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install curlylint run: pip install curlylint diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml deleted file mode 100644 index 78b6e142e..000000000 --- a/.github/workflows/django-tests.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Run Python Tests -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - - runs-on: ubuntu-20.04 - services: - postgres: - image: postgres:13 - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: hunter2 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - name: Install Dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - name: Check migrations up-to-date - run: | - python ./manage.py makemigrations --check - env: - SECRET_KEY: beepbeep - DOMAIN: your.domain.here - EMAIL_HOST: "" - EMAIL_HOST_USER: "" - EMAIL_HOST_PASSWORD: "" - - name: Run Tests - env: - SECRET_KEY: beepbeep - DEBUG: false - USE_HTTPS: true - DOMAIN: your.domain.here - BOOKWYRM_DATABASE_BACKEND: postgres - MEDIA_ROOT: images/ - POSTGRES_PASSWORD: hunter2 - POSTGRES_USER: postgres - POSTGRES_DB: github_actions - POSTGRES_HOST: 127.0.0.1 - CELERY_BROKER: "" - REDIS_BROKER_PORT: 6379 - REDIS_BROKER_PASSWORD: beep - USE_DUMMY_CACHE: true - FLOWER_PORT: 8888 - EMAIL_HOST: "smtp.mailgun.org" - EMAIL_PORT: 587 - EMAIL_HOST_USER: "" - EMAIL_HOST_PASSWORD: "" - EMAIL_USE_TLS: true - ENABLE_PREVIEW_IMAGES: false - ENABLE_THUMBNAIL_GENERATION: true - HTTP_X_FORWARDED_PROTO: false - run: | - pytest -n 3 diff --git a/.github/workflows/lint-frontend.yaml b/.github/workflows/lint-frontend.yaml index 0d0559e40..21f11ebf3 100644 --- a/.github/workflows/lint-frontend.yaml +++ b/.github/workflows/lint-frontend.yaml @@ -19,7 +19,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it. - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install modules run: npm install stylelint stylelint-config-recommended stylelint-config-standard stylelint-order eslint diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml deleted file mode 100644 index 1a641edd2..000000000 --- a/.github/workflows/mypy.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Mypy - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.9 - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - name: Install Dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - name: Analysing the code with mypy - env: - SECRET_KEY: beepbeep - DEBUG: false - USE_HTTPS: true - DOMAIN: your.domain.here - BOOKWYRM_DATABASE_BACKEND: postgres - MEDIA_ROOT: images/ - POSTGRES_PASSWORD: hunter2 - POSTGRES_USER: postgres - POSTGRES_DB: github_actions - POSTGRES_HOST: 127.0.0.1 - CELERY_BROKER: "" - REDIS_BROKER_PORT: 6379 - REDIS_BROKER_PASSWORD: beep - USE_DUMMY_CACHE: true - FLOWER_PORT: 8888 - EMAIL_HOST: "smtp.mailgun.org" - EMAIL_PORT: 587 - EMAIL_HOST_USER: "" - EMAIL_HOST_PASSWORD: "" - EMAIL_USE_TLS: true - ENABLE_PREVIEW_IMAGES: false - ENABLE_THUMBNAIL_GENERATION: true - HTTP_X_FORWARDED_PROTO: false - run: | - mypy bookwyrm celerywyrm diff --git a/.github/workflows/prettier.yaml b/.github/workflows/prettier.yaml index 501516ae1..9c05c7476 100644 --- a/.github/workflows/prettier.yaml +++ b/.github/workflows/prettier.yaml @@ -14,7 +14,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it. - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install modules run: npm install prettier@2.5.1 diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml deleted file mode 100644 index 3811c97d3..000000000 --- a/.github/workflows/pylint.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Pylint - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.9 - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - name: Install Dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - name: Analysing the code with pylint - run: | - pylint bookwyrm/ - diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 000000000..01241b467 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,99 @@ +name: Python +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +# overrides for .env.example +env: + POSTGRES_HOST: 127.0.0.1 + PGPORT: 5432 + POSTGRES_USER: postgres + POSTGRES_PASSWORD: hunter2 + POSTGRES_DB: github_actions + SECRET_KEY: beepbeep + EMAIL_HOST_USER: "" + EMAIL_HOST_PASSWORD: "" + +jobs: + pytest: + name: Tests (pytest) + runs-on: ubuntu-latest + services: + postgres: + image: postgres:13 + env: # does not inherit from jobs.build.env + POSTGRES_USER: postgres + POSTGRES_PASSWORD: hunter2 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + cache: pip + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pytest-github-actions-annotate-failures + - name: Set up .env + run: cp .env.example .env + - name: Check migrations up-to-date + run: python ./manage.py makemigrations --check + - name: Run Tests + run: pytest -n 3 + + pylint: + name: Linting (pylint) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + cache: pip + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Analyse code with pylint + run: pylint bookwyrm/ + + mypy: + name: Typing (mypy) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + cache: pip + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Set up .env + run: cp .env.example .env + - name: Analyse code with mypy + run: mypy bookwyrm celerywyrm + + black: + name: Formatting (black; run ./bw-dev black to fix) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: psf/black@stable + with: + version: "22.*" diff --git a/.gitignore b/.gitignore index ec2a08f80..755375b34 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ # BookWyrm .env /images/ +/static/ bookwyrm/static/css/bookwyrm.css bookwyrm/static/css/themes/ !bookwyrm/static/css/themes/bookwyrm-*.scss diff --git a/Dockerfile b/Dockerfile index b3cd26e88..82b0c92c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9 +FROM python:3.11 ENV PYTHONUNBUFFERED 1 diff --git a/VERSION b/VERSION index 39e898a4f..7486fdbc5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.1 +0.7.2 diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index fbbc18f73..efc9d8da2 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -20,6 +20,7 @@ from bookwyrm.tasks import app, MISC logger = logging.getLogger(__name__) +# pylint: disable=invalid-name TBookWyrmModel = TypeVar("TBookWyrmModel", bound=base_model.BookWyrmModel) @@ -423,6 +424,7 @@ def get_activitypub_data(url): "Date": now, "Signature": make_signature("get", sender, url, now), }, + timeout=15, ) except requests.RequestException: raise ConnectorException() diff --git a/bookwyrm/activitypub/person.py b/bookwyrm/activitypub/person.py index 85cf44409..dfec92e4c 100644 --- a/bookwyrm/activitypub/person.py +++ b/bookwyrm/activitypub/person.py @@ -1,5 +1,5 @@ """ actor serializer """ -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import Dict from .base_activity import ActivityObject @@ -35,7 +35,7 @@ class Person(ActivityObject): endpoints: Dict = None name: str = None summary: str = None - icon: Image = field(default_factory=lambda: {}) + icon: Image = None bookwyrmUser: bool = False manuallyApprovesFollowers: str = False discoverable: str = False diff --git a/bookwyrm/apps.py b/bookwyrm/apps.py index b0c3e3fa4..41b1a17a2 100644 --- a/bookwyrm/apps.py +++ b/bookwyrm/apps.py @@ -1,4 +1,5 @@ """Do further startup configuration and initialization""" + import os import urllib import logging @@ -14,16 +15,16 @@ def download_file(url, destination): """Downloads a file to the given path""" try: # Ensure our destination directory exists - os.makedirs(os.path.dirname(destination)) + os.makedirs(os.path.dirname(destination), exist_ok=True) with urllib.request.urlopen(url) as stream: with open(destination, "b+w") as outfile: outfile.write(stream.read()) - except (urllib.error.HTTPError, urllib.error.URLError): - logger.info("Failed to download file %s", url) - except OSError: - logger.info("Couldn't open font file %s for writing", destination) - except: # pylint: disable=bare-except - logger.info("Unknown error in file download") + except (urllib.error.HTTPError, urllib.error.URLError) as err: + logger.error("Failed to download file %s: %s", url, err) + except OSError as err: + logger.error("Couldn't open font file %s for writing: %s", destination, err) + except Exception as err: # pylint:disable=broad-except + logger.error("Unknown error in file download: %s", err) class BookwyrmConfig(AppConfig): diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 8b6dcb885..aa8edbeae 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -3,7 +3,9 @@ from __future__ import annotations from abc import ABC, abstractmethod from typing import Optional, TypedDict, Any, Callable, Union, Iterator from urllib.parse import quote_plus -import imghdr + +# pylint: disable-next=deprecated-module +import imghdr # Deprecated in 3.11 for removal in 3.13; no good alternative yet import logging import re import asyncio diff --git a/bookwyrm/forms/links.py b/bookwyrm/forms/links.py index d2fd5f116..345c5c1d4 100644 --- a/bookwyrm/forms/links.py +++ b/bookwyrm/forms/links.py @@ -1,4 +1,5 @@ """ using django model forms """ + from urllib.parse import urlparse from django.utils.translation import gettext_lazy as _ @@ -37,10 +38,9 @@ class FileLinkForm(CustomForm): ), ) if ( - not self.instance - and models.FileLink.objects.filter( - url=url, book=book, filetype=filetype - ).exists() + models.FileLink.objects.filter(url=url, book=book, filetype=filetype) + .exclude(pk=self.instance) + .exists() ): # pylint: disable=line-too-long self.add_error( diff --git a/bookwyrm/isbn/isbn.py b/bookwyrm/isbn/isbn.py index 56062ff7b..d14dc2619 100644 --- a/bookwyrm/isbn/isbn.py +++ b/bookwyrm/isbn/isbn.py @@ -26,7 +26,7 @@ class IsbnHyphenator: def update_range_message(self) -> None: """Download the range message xml file and save it locally""" - response = requests.get(self.__range_message_url) + response = requests.get(self.__range_message_url, timeout=15) with open(self.__range_file_path, "w", encoding="utf-8") as file: file.write(response.text) self.__element_tree = None diff --git a/bookwyrm/management/commands/instance_version.py b/bookwyrm/management/commands/instance_version.py deleted file mode 100644 index ca150d640..000000000 --- a/bookwyrm/management/commands/instance_version.py +++ /dev/null @@ -1,54 +0,0 @@ -""" Get your admin code to allow install """ -from django.core.management.base import BaseCommand - -from bookwyrm import models -from bookwyrm.settings import VERSION - - -# pylint: disable=no-self-use -class Command(BaseCommand): - """command-line options""" - - help = "What version is this?" - - def add_arguments(self, parser): - """specify which function to run""" - parser.add_argument( - "--current", - action="store_true", - help="Version stored in database", - ) - parser.add_argument( - "--target", - action="store_true", - help="Version stored in settings", - ) - parser.add_argument( - "--update", - action="store_true", - help="Update database version", - ) - - # pylint: disable=unused-argument - def handle(self, *args, **options): - """execute init""" - site = models.SiteSettings.objects.get() - current = site.version or "0.0.1" - target = VERSION - if options.get("current"): - print(current) - return - - if options.get("target"): - print(target) - return - - if options.get("update"): - site.version = target - site.save() - return - - if current != target: - print(f"{current}/{target}") - else: - print(current) diff --git a/bookwyrm/migrations/0190_book_search_updates.py b/bookwyrm/migrations/0190_book_search_updates.py new file mode 100644 index 000000000..52d80fcb9 --- /dev/null +++ b/bookwyrm/migrations/0190_book_search_updates.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.20 on 2023-11-24 17:11 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("bookwyrm", "0188_theme_loads"), + ] + + operations = [ + migrations.RemoveIndex( + model_name="author", + name="bookwyrm_au_search__b050a8_gin", + ), + ] diff --git a/bookwyrm/migrations/0191_migrate_search_vec_triggers_to_pgtriggers.py b/bookwyrm/migrations/0191_migrate_search_vec_triggers_to_pgtriggers.py new file mode 100644 index 000000000..03442298f --- /dev/null +++ b/bookwyrm/migrations/0191_migrate_search_vec_triggers_to_pgtriggers.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.20 on 2023-11-25 00:47 + +from importlib import import_module +import re + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + +trigger_migration = import_module("bookwyrm.migrations.0077_auto_20210623_2155") + +# it's _very_ convenient for development that this migration be reversible +search_vector_trigger = trigger_migration.Migration.operations[4] +author_search_vector_trigger = trigger_migration.Migration.operations[5] + + +assert re.search(r"\bCREATE TRIGGER search_vector_trigger\b", search_vector_trigger.sql) +assert re.search( + r"\bCREATE TRIGGER author_search_vector_trigger\b", + author_search_vector_trigger.sql, +) + + +class Migration(migrations.Migration): + dependencies = [ + ("bookwyrm", "0190_book_search_updates"), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name="book", + trigger=pgtrigger.compiler.Trigger( + name="update_search_vector_on_book_edit", + sql=pgtrigger.compiler.UpsertTriggerSql( + func="new.search_vector := setweight(coalesce(nullif(to_tsvector('english', new.title), ''), to_tsvector('simple', new.title)), 'A') || setweight(to_tsvector('english', coalesce(new.subtitle, '')), 'B') || (SELECT setweight(to_tsvector('simple', coalesce(array_to_string(array_agg(bookwyrm_author.name), ' '), '')), 'C') FROM bookwyrm_author LEFT JOIN bookwyrm_book_authors ON bookwyrm_author.id = bookwyrm_book_authors.author_id WHERE bookwyrm_book_authors.book_id = new.id ) || setweight(to_tsvector('english', coalesce(new.series, '')), 'D');RETURN NEW;", + hash="77d6399497c0a89b0bf09d296e33c396da63705c", + operation='INSERT OR UPDATE OF "title", "subtitle", "series", "search_vector"', + pgid="pgtrigger_update_search_vector_on_book_edit_bec58", + table="bookwyrm_book", + when="BEFORE", + ), + ), + ), + pgtrigger.migrations.AddTrigger( + model_name="author", + trigger=pgtrigger.compiler.Trigger( + name="reset_search_vector_on_author_edit", + sql=pgtrigger.compiler.UpsertTriggerSql( + func="WITH updated_books AS (SELECT book_id FROM bookwyrm_book_authors WHERE author_id = new.id ) UPDATE bookwyrm_book SET search_vector = '' FROM updated_books WHERE id = updated_books.book_id;RETURN NEW;", + hash="e7bbf08711ff3724c58f4d92fb7a082ffb3d7826", + operation='UPDATE OF "name"', + pgid="pgtrigger_reset_search_vector_on_author_edit_a447c", + table="bookwyrm_author", + when="AFTER", + ), + ), + ), + migrations.RunSQL( + sql="""DROP TRIGGER IF EXISTS search_vector_trigger ON bookwyrm_book; + DROP FUNCTION IF EXISTS book_trigger; + """, + reverse_sql=search_vector_trigger.sql, + ), + migrations.RunSQL( + sql="""DROP TRIGGER IF EXISTS author_search_vector_trigger ON bookwyrm_author; + DROP FUNCTION IF EXISTS author_trigger; + """, + reverse_sql=author_search_vector_trigger.sql, + ), + migrations.RunSQL( + # Recalculate book search vector for any missed author name changes + # due to bug in JOIN in the old trigger. + sql="UPDATE bookwyrm_book SET search_vector = NULL;", + reverse_sql=migrations.RunSQL.noop, + ), + ] diff --git a/bookwyrm/migrations/0192_make_page_positions_text.py b/bookwyrm/migrations/0192_make_page_positions_text.py new file mode 100644 index 000000000..940a9e941 --- /dev/null +++ b/bookwyrm/migrations/0192_make_page_positions_text.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.23 on 2024-01-04 23:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0191_merge_20240102_0326"), + ] + + operations = [ + migrations.AlterField( + model_name="quotation", + name="endposition", + field=models.TextField(blank=True, null=True), + ), + migrations.AlterField( + model_name="quotation", + name="position", + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py b/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py new file mode 100644 index 000000000..db67b4e92 --- /dev/null +++ b/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.23 on 2024-01-02 19:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0191_merge_20240102_0326"), + ] + + operations = [ + migrations.RenameField( + model_name="sitesettings", + old_name="version", + new_name="available_version", + ), + ] diff --git a/bookwyrm/migrations/0192_sitesettings_user_exports_enabled.py b/bookwyrm/migrations/0192_sitesettings_user_exports_enabled.py new file mode 100644 index 000000000..ec5b411e2 --- /dev/null +++ b/bookwyrm/migrations/0192_sitesettings_user_exports_enabled.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.23 on 2024-01-16 10:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0191_merge_20240102_0326"), + ] + + operations = [ + migrations.AddField( + model_name="sitesettings", + name="user_exports_enabled", + field=models.BooleanField(default=False), + ), + ] diff --git a/bookwyrm/migrations/0193_merge_20240203_1539.py b/bookwyrm/migrations/0193_merge_20240203_1539.py new file mode 100644 index 000000000..a88568ba1 --- /dev/null +++ b/bookwyrm/migrations/0193_merge_20240203_1539.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.23 on 2024-02-03 15:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0192_make_page_positions_text"), + ("bookwyrm", "0192_sitesettings_user_exports_enabled"), + ] + + operations = [] diff --git a/bookwyrm/migrations/0194_merge_20240203_1619.py b/bookwyrm/migrations/0194_merge_20240203_1619.py new file mode 100644 index 000000000..a5c18e300 --- /dev/null +++ b/bookwyrm/migrations/0194_merge_20240203_1619.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.23 on 2024-02-03 16:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0192_rename_version_sitesettings_available_version"), + ("bookwyrm", "0193_merge_20240203_1539"), + ] + + operations = [] diff --git a/bookwyrm/migrations/0195_alter_user_preferred_language.py b/bookwyrm/migrations/0195_alter_user_preferred_language.py new file mode 100644 index 000000000..1fbfa7304 --- /dev/null +++ b/bookwyrm/migrations/0195_alter_user_preferred_language.py @@ -0,0 +1,46 @@ +# Generated by Django 3.2.23 on 2024-02-21 00:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0194_merge_20240203_1619"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="preferred_language", + field=models.CharField( + blank=True, + choices=[ + ("en-us", "English"), + ("ca-es", "Català (Catalan)"), + ("de-de", "Deutsch (German)"), + ("eo-uy", "Esperanto (Esperanto)"), + ("es-es", "Español (Spanish)"), + ("eu-es", "Euskara (Basque)"), + ("gl-es", "Galego (Galician)"), + ("it-it", "Italiano (Italian)"), + ("ko-kr", "한국어 (Korean)"), + ("fi-fi", "Suomi (Finnish)"), + ("fr-fr", "Français (French)"), + ("lt-lt", "Lietuvių (Lithuanian)"), + ("nl-nl", "Nederlands (Dutch)"), + ("no-no", "Norsk (Norwegian)"), + ("pl-pl", "Polski (Polish)"), + ("pt-br", "Português do Brasil (Brazilian Portuguese)"), + ("pt-pt", "Português Europeu (European Portuguese)"), + ("ro-ro", "Română (Romanian)"), + ("sv-se", "Svenska (Swedish)"), + ("uk-ua", "Українська (Ukrainian)"), + ("zh-hans", "简体中文 (Simplified Chinese)"), + ("zh-hant", "繁體中文 (Traditional Chinese)"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/migrations/0196_merge_pr3134_into_main.py b/bookwyrm/migrations/0196_merge_pr3134_into_main.py new file mode 100644 index 000000000..0862f11b2 --- /dev/null +++ b/bookwyrm/migrations/0196_merge_pr3134_into_main.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.23 on 2024-03-18 00:48 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0191_migrate_search_vec_triggers_to_pgtriggers"), + ("bookwyrm", "0195_alter_user_preferred_language"), + ] + + operations = [] diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index d0a941f43..db737b8bc 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -152,8 +152,9 @@ class ActivitypubMixin: # find anyone who's tagged in a status, for example mentions = self.recipients if hasattr(self, "recipients") else [] - # we always send activities to explicitly mentioned users' inboxes - recipients = [u.inbox for u in mentions or [] if not u.local] + # we always send activities to explicitly mentioned users (using shared inboxes + # where available to avoid duplicate submissions to a given instance) + recipients = {u.shared_inbox or u.inbox for u in mentions if not u.local} # unless it's a dm, all the followers should receive the activity if privacy != "direct": @@ -173,18 +174,18 @@ class ActivitypubMixin: if user: queryset = queryset.filter(following=user) - # ideally, we will send to shared inboxes for efficiency - shared_inboxes = ( - queryset.filter(shared_inbox__isnull=False) - .values_list("shared_inbox", flat=True) - .distinct() + # as above, we prefer shared inboxes if available + recipients.update( + queryset.filter(shared_inbox__isnull=False).values_list( + "shared_inbox", flat=True + ) ) - # but not everyone has a shared inbox - inboxes = queryset.filter(shared_inbox__isnull=True).values_list( - "inbox", flat=True + recipients.update( + queryset.filter(shared_inbox__isnull=True).values_list( + "inbox", flat=True + ) ) - recipients += list(shared_inboxes) + list(inboxes) - return list(set(recipients)) + return list(recipients) def to_activity_dataclass(self): """convert from a model to an activity""" diff --git a/bookwyrm/models/author.py b/bookwyrm/models/author.py index 981e3c0cc..154b00ccb 100644 --- a/bookwyrm/models/author.py +++ b/bookwyrm/models/author.py @@ -2,11 +2,12 @@ import re from typing import Tuple, Any -from django.contrib.postgres.indexes import GinIndex from django.db import models +import pgtrigger from bookwyrm import activitypub from bookwyrm.settings import DOMAIN +from bookwyrm.utils.db import format_trigger from .book import BookDataModel from . import fields @@ -67,9 +68,28 @@ class Author(BookDataModel): """editions and works both use "book" instead of model_name""" return f"https://{DOMAIN}/author/{self.id}" - activity_serializer = activitypub.Author - class Meta: - """sets up postgres GIN index field""" + """sets up indexes and triggers""" - indexes = (GinIndex(fields=["search_vector"]),) + triggers = [ + pgtrigger.Trigger( + name="reset_search_vector_on_author_edit", + when=pgtrigger.After, + operation=pgtrigger.UpdateOf("name"), + func=format_trigger( + """WITH updated_books AS ( + SELECT book_id + FROM bookwyrm_book_authors + WHERE author_id = new.id + ) + UPDATE bookwyrm_book + SET search_vector = '' + FROM updated_books + WHERE id = updated_books.book_id; + RETURN new; + """ + ), + ) + ] + + activity_serializer = activitypub.Author diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index 6893b9da1..e167e2138 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from model_utils import FieldTracker from model_utils.managers import InheritanceManager from imagekit.models import ImageSpecField +import pgtrigger from bookwyrm import activitypub from bookwyrm.isbn.isbn import hyphenator_singleton as hyphenator @@ -24,6 +25,7 @@ from bookwyrm.settings import ( ENABLE_PREVIEW_IMAGES, ENABLE_THUMBNAIL_GENERATION, ) +from bookwyrm.utils.db import format_trigger from .activitypub_mixin import OrderedCollectionPageMixin, ObjectMixin from .base_model import BookWyrmModel @@ -232,9 +234,39 @@ class Book(BookDataModel): ) class Meta: - """sets up postgres GIN index field""" + """set up indexes and triggers""" + + # pylint: disable=line-too-long indexes = (GinIndex(fields=["search_vector"]),) + triggers = [ + pgtrigger.Trigger( + name="update_search_vector_on_book_edit", + when=pgtrigger.Before, + operation=pgtrigger.Insert + | pgtrigger.UpdateOf("title", "subtitle", "series", "search_vector"), + func=format_trigger( + """new.search_vector := + -- title, with priority A (parse in English, default to simple if empty) + setweight(COALESCE(nullif( + to_tsvector('english', new.title), ''), + to_tsvector('simple', new.title)), 'A') || + -- subtitle, with priority B (always in English?) + setweight(to_tsvector('english', COALESCE(new.subtitle, '')), 'B') || + -- list of authors, with priority C (TODO: add aliases?, bookwyrm-social#3063) + (SELECT setweight(to_tsvector('simple', COALESCE(array_to_string(ARRAY_AGG(bookwyrm_author.name), ' '), '')), 'C') + FROM bookwyrm_author + LEFT JOIN bookwyrm_book_authors + ON bookwyrm_author.id = bookwyrm_book_authors.author_id + WHERE bookwyrm_book_authors.book_id = new.id + ) || + --- last: series name, with lowest priority + setweight(to_tsvector('english', COALESCE(new.series, '')), 'D'); + RETURN new; + """ + ), + ) + ] class Work(OrderedCollectionPageMixin, Book): diff --git a/bookwyrm/models/bookwyrm_export_job.py b/bookwyrm/models/bookwyrm_export_job.py index 1f6085e0c..2f32cbd29 100644 --- a/bookwyrm/models/bookwyrm_export_job.py +++ b/bookwyrm/models/bookwyrm_export_job.py @@ -80,10 +80,7 @@ def json_export( exported_user = user.to_activity() # I don't love this but it prevents a JSON encoding error # when there is no user image - if isinstance( - exported_user["icon"], - dataclasses._MISSING_TYPE, # pylint: disable=protected-access - ): + if exported_user.get("icon") in (None, dataclasses.MISSING): exported_user["icon"] = {} else: # change the URL to be relative to the JSON file diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 4bd580705..55ec25466 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -482,7 +482,7 @@ class ImageField(ActivitypubFieldMixin, models.ImageField): if not url: return None - return activitypub.Document(url=url, name=alt) + return activitypub.Image(url=url, name=alt) def field_from_activity(self, value, allow_external_connections=True): image_slug = value diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index bd53f1f07..201a499e5 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -10,8 +10,11 @@ from django.dispatch import receiver from django.utils import timezone from model_utils import FieldTracker +from bookwyrm.connectors.abstract_connector import get_data from bookwyrm.preview_images import generate_site_preview_image_task from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, STATIC_FULL_URL +from bookwyrm.settings import RELEASE_API +from bookwyrm.tasks import app, MISC from .base_model import BookWyrmModel, new_access_code from .user import User from .fields import get_absolute_url @@ -45,7 +48,7 @@ class SiteSettings(SiteModel): default_theme = models.ForeignKey( "Theme", null=True, blank=True, on_delete=models.SET_NULL ) - version = models.CharField(null=True, blank=True, max_length=10) + available_version = models.CharField(null=True, blank=True, max_length=10) # admin setup options install_mode = models.BooleanField(default=False) @@ -96,6 +99,7 @@ class SiteSettings(SiteModel): imports_enabled = models.BooleanField(default=True) import_size_limit = models.IntegerField(default=0) import_limit_reset = models.IntegerField(default=0) + user_exports_enabled = models.BooleanField(default=False) user_import_time_limit = models.IntegerField(default=48) field_tracker = FieldTracker(fields=["name", "instance_tagline", "logo"]) @@ -244,3 +248,14 @@ def preview_image(instance, *args, **kwargs): if len(changed_fields) > 0: generate_site_preview_image_task.delay() + + +@app.task(queue=MISC) +def check_for_updates_task(): + """See if git remote knows about a new version""" + site = SiteSettings.objects.get() + release = get_data(RELEASE_API, timeout=3) + available_version = release.get("tag_name", None) + if available_version: + site.available_version = available_version + site.save(update_fields=["available_version"]) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index cc44fe2bf..f6235dab6 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -12,6 +12,8 @@ from django.db.models import Q from django.dispatch import receiver from django.template.loader import get_template from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy from model_utils import FieldTracker from model_utils.managers import InheritanceManager @@ -107,14 +109,14 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): @property def recipients(self): """tagged users who definitely need to get this status in broadcast""" - mentions = [u for u in self.mention_users.all() if not u.local] + mentions = {u for u in self.mention_users.all() if not u.local} if ( hasattr(self, "reply_parent") and self.reply_parent and not self.reply_parent.user.local ): - mentions.append(self.reply_parent.user) - return list(set(mentions)) + mentions.add(self.reply_parent.user) + return list(mentions) @classmethod def ignore_activity( @@ -178,6 +180,24 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): """you can't boost dms""" return self.privacy in ["unlisted", "public"] + @property + def page_title(self): + """title of the page when only this status is shown""" + return _("%(display_name)s's status") % {"display_name": self.user.display_name} + + @property + def page_description(self): + """description of the page in meta tags when only this status is shown""" + return None + + @property + def page_image(self): + """image to use as preview in meta tags when only this status is shown""" + if self.mention_books.exists(): + book = self.mention_books.first() + return book.preview_image or book.cover + return self.user.preview_image + def to_replies(self, **kwargs): """helper function for loading AP serialized replies to a status""" return self.to_ordered_collection( @@ -301,6 +321,10 @@ class BookStatus(Status): abstract = True + @property + def page_image(self): + return self.book.preview_image or self.book.cover or super().page_image + class Comment(BookStatus): """like a review but without a rating and transient""" @@ -332,17 +356,26 @@ class Comment(BookStatus): activity_serializer = activitypub.Comment + @property + def page_title(self): + return _("%(display_name)s's comment on %(book_title)s") % { + "display_name": self.user.display_name, + "book_title": self.book.title, + } + class Quotation(BookStatus): """like a review but without a rating and transient""" quote = fields.HtmlField() raw_quote = models.TextField(blank=True, null=True) - position = models.IntegerField( - validators=[MinValueValidator(0)], null=True, blank=True + position = models.TextField( + null=True, + blank=True, ) - endposition = models.IntegerField( - validators=[MinValueValidator(0)], null=True, blank=True + endposition = models.TextField( + null=True, + blank=True, ) position_mode = models.CharField( max_length=3, @@ -374,6 +407,13 @@ class Quotation(BookStatus): activity_serializer = activitypub.Quotation + @property + def page_title(self): + return _("%(display_name)s's quote from %(book_title)s") % { + "display_name": self.user.display_name, + "book_title": self.book.title, + } + class Review(BookStatus): """a book review""" @@ -403,6 +443,13 @@ class Review(BookStatus): """indicate the book in question for mastodon (or w/e) users""" return self.content + @property + def page_title(self): + return _("%(display_name)s's review of %(book_title)s") % { + "display_name": self.user.display_name, + "book_title": self.book.title, + } + activity_serializer = activitypub.Review pure_type = "Article" @@ -426,6 +473,18 @@ class ReviewRating(Review): template = get_template("snippets/generated_status/rating.html") return template.render({"book": self.book, "rating": self.rating}).strip() + @property + def page_description(self): + return ngettext_lazy( + "%(display_name)s rated %(book_title)s: %(display_rating).1f star", + "%(display_name)s rated %(book_title)s: %(display_rating).1f stars", + "display_rating", + ) % { + "display_name": self.user.display_name, + "book_title": self.book.title, + "display_rating": self.rating, + } + activity_serializer = activitypub.Rating pure_type = "Note" diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index aba372abc..995f25bfd 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -1,4 +1,5 @@ """ Generate social media preview images for twitter/mastodon/etc """ + import math import os import textwrap @@ -42,8 +43,8 @@ def get_imagefont(name, size): return ImageFont.truetype(path, size) except KeyError: logger.error("Font %s not found in config", name) - except OSError: - logger.error("Could not load font %s from file", name) + except OSError as err: + logger.error("Could not load font %s from file: %s", name, err) return ImageFont.load_default() @@ -59,7 +60,7 @@ def get_font(weight, size=28): font.set_variation_by_name("Bold") if weight == "regular": font.set_variation_by_name("Regular") - except AttributeError: + except OSError: pass return font diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index fcc91857a..77bec0d8e 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -30,6 +30,9 @@ RELEASE_API = env( PAGE_LENGTH = env.int("PAGE_LENGTH", 15) DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English") +# TODO: extend maximum age to 1 year once termination of active sessions +# is implemented (see bookwyrm-social#2278, bookwyrm-social#3082). +SESSION_COOKIE_AGE = env.int("SESSION_COOKIE_AGE", 3600 * 24 * 30) # 1 month JS_CACHE = "8a89cad7" @@ -105,6 +108,7 @@ INSTALLED_APPS = [ "celery", "django_celery_beat", "imagekit", + "pgtrigger", "storages", ] @@ -318,6 +322,7 @@ LANGUAGES = [ ("eu-es", _("Euskara (Basque)")), ("gl-es", _("Galego (Galician)")), ("it-it", _("Italiano (Italian)")), + ("ko-kr", _("한국어 (Korean)")), ("fi-fi", _("Suomi (Finnish)")), ("fr-fr", _("Français (French)")), ("lt-lt", _("Lietuvių (Lithuanian)")), @@ -347,8 +352,7 @@ USE_L10N = True USE_TZ = True -agent = requests.utils.default_user_agent() -USER_AGENT = f"{agent} (BookWyrm/{VERSION}; +https://{DOMAIN}/)" +USER_AGENT = f"BookWyrm (BookWyrm/{VERSION}; +https://{DOMAIN}/)" # Imagekit generated thumbnails ENABLE_THUMBNAIL_GENERATION = env.bool("ENABLE_THUMBNAIL_GENERATION", False) @@ -442,3 +446,7 @@ if HTTP_X_FORWARDED_PROTO: # Do not change this setting unless you already have an existing # user with the same username - in which case you should change it! INSTANCE_ACTOR_USERNAME = "bookwyrm.instance.actor" + +# We only allow specifying DATA_UPLOAD_MAX_MEMORY_SIZE in MiB from .env +# (note the difference in variable names). +DATA_UPLOAD_MAX_MEMORY_SIZE = env.int("DATA_UPLOAD_MAX_MEMORY_MiB", 100) << 20 diff --git a/bookwyrm/static/js/autocomplete.js b/bookwyrm/static/js/autocomplete.js index a98cd9634..6836d356d 100644 --- a/bookwyrm/static/js/autocomplete.js +++ b/bookwyrm/static/js/autocomplete.js @@ -111,6 +111,10 @@ const tries = { }, }, f: { + b: { + 2: "FB2", + 3: "FB3", + }, l: { a: { c: "FLAC", diff --git a/bookwyrm/templates/about/about.html b/bookwyrm/templates/about/about.html index 6705793d5..ef3f34037 100644 --- a/bookwyrm/templates/about/about.html +++ b/bookwyrm/templates/about/about.html @@ -31,10 +31,10 @@
-{% trans "A confirmation code has been sent to the email address you used to register your account." %}
diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 7ecf10b70..1b6cf29ff 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -41,7 +41,7 @@{{ login_form.non_field_errors }}
{% endif %} @@ -20,13 +20,15 @@- {% trans "More about this site" %} + {% trans "More about this site" %}
{{ login_form.non_field_errors }}
{% endif %} @@ -16,13 +16,15 @@- {% trans "More about this site" %} + {% trans "More about this site" %}
- {% id_to_username request.user.moved_to as username %} + {% id_to_username request.user.moved_to as username %} {% blocktrans trimmed with moved_to=user.moved_to %} You have moved your account to {{ username }} {% endblocktrans %} diff --git a/bookwyrm/templates/notifications/items/move_user.html b/bookwyrm/templates/notifications/items/move_user.html index b94d96dc4..3121d3f45 100644 --- a/bookwyrm/templates/notifications/items/move_user.html +++ b/bookwyrm/templates/notifications/items/move_user.html @@ -14,7 +14,7 @@ {% block description %} {% if related_user_moved_to %} - {% id_to_username request.user.moved_to as username %} + {% id_to_username related_user_moved_to as username %} {% blocktrans trimmed %} {{ related_user }} has moved to {{ username }} {% endblocktrans %} diff --git a/bookwyrm/templates/preferences/export-user.html b/bookwyrm/templates/preferences/export-user.html index a468c3f74..955cff656 100644 --- a/bookwyrm/templates/preferences/export-user.html +++ b/bookwyrm/templates/preferences/export-user.html @@ -14,31 +14,29 @@
{% trans "You can create an export file here. This will allow you to migrate your data to another BookWyrm account." %}
{% trans "In your new BookWyrm account can choose what to import: you will not have to import everything that is exported." %}
@@ -46,7 +44,18 @@ {% trans "If you wish to migrate any statuses (comments, reviews, or quotes) you must either set the account you are moving to as an alias of this one, or move this account to the new account, before you import your user data." %} {% endspaceless %}
- {% if next_available %} + {% if not site.user_exports_enabled %} +
+ {% trans "New user exports are currently disabled." %}
+ {% if perms.bookwyrm.edit_instance_settings %}
+
+ {% url 'settings-imports' as url %}
+ {% blocktrans trimmed %}
+ User exports settings can be changed from the Imports page in the Admin dashboard.
+ {% endblocktrans %}
+ {% endif%}
+
{% blocktrans trimmed %} You will be able to create a new export file at {{ next_available }} diff --git a/bookwyrm/templates/search/author.html b/bookwyrm/templates/search/author.html new file mode 100644 index 000000000..d42c3b54f --- /dev/null +++ b/bookwyrm/templates/search/author.html @@ -0,0 +1,17 @@ +{% extends 'search/layout.html' %} + +{% block panel %} + +{% if results %} +
{% if request.user.is_authenticated %} {% if not remote %} - + {% trans "Load results from other catalogues" %} {% else %} diff --git a/bookwyrm/templates/search/layout.html b/bookwyrm/templates/search/layout.html index 8cf47b371..59ea0304e 100644 --- a/bookwyrm/templates/search/layout.html +++ b/bookwyrm/templates/search/layout.html @@ -20,6 +20,7 @@
+ {% trans "Name" %} + | ++ {% trans "Celery task" %} + | ++ {% trans "Date changed" %} + | ++ {% trans "Last run at" %} + | ++ {% trans "Schedule" %} + | ++ {% trans "Schedule ID" %} + | ++ {% trans "Enabled" %} + | +
---|---|---|---|---|---|---|
+ {{ task.name }} + | ++ {{ task.task }} + | ++ {{ task.date_changed }} + | ++ {{ task.last_run_at }} + | ++ {% firstof task.interval task.crontab "None" %} + | ++ {{ task.interval.id }} + | ++ + {% if task.enabled %} + + {% endif %} + {{ task.enabled|yesno }} + + {% if task.name != "celery.backend_cleanup" %} + + {% endif %} + | +
+ {% trans "No scheduled tasks" %} + | +
+ {% trans "ID" %} + | ++ {% trans "Schedule" %} + | ++ {% trans "Tasks" %} + | +
---|---|---|
+ {{ schedule.id }} + | ++ {{ schedule }} + | ++ {{ schedule.periodictask_set.count }} + | +
+ {% trans "No schedules found" %} + | +
%(level)s
."
+msgstr ""
+
+#: bookwyrm/templates/403.html:15
+msgid "If you think you should have access, please speak to your BookWyrm server administrator."
+msgstr ""
+
+#: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8
+msgid "Not Found"
+msgstr "찾을 수 없음"
+
+#: bookwyrm/templates/404.html:9
+msgid "The page you requested doesn't seem to exist!"
+msgstr ""
+
+#: bookwyrm/templates/413.html:4 bookwyrm/templates/413.html:8
+msgid "File too large"
+msgstr "너무 큰 파일"
+
+#: bookwyrm/templates/413.html:9
+msgid "The file you are uploading is too large."
+msgstr ""
+
+#: bookwyrm/templates/413.html:11
+msgid "\n"
+" You you can try using a smaller file, or ask your BookWyrm server administrator to increase the DATA_UPLOAD_MAX_MEMORY_SIZE
setting.\n"
+" "
+msgstr ""
+
+#: bookwyrm/templates/500.html:4
+msgid "Oops!"
+msgstr "이런!"
+
+#: bookwyrm/templates/500.html:8
+msgid "Server Error"
+msgstr "서버 오류"
+
+#: bookwyrm/templates/500.html:9
+msgid "Something went wrong! Sorry about that."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:9
+#: bookwyrm/templates/about/layout.html:35
+msgid "About"
+msgstr "정보"
+
+#: bookwyrm/templates/about/about.html:21
+#: bookwyrm/templates/get_started/layout.html:22
+#, python-format
+msgid "Welcome to %(site_name)s!"
+msgstr "%(site_name)s에 어서오세요!"
+
+#: bookwyrm/templates/about/about.html:25
+#, python-format
+msgid "%(site_name)s is part of BookWyrm, a network of independent, self-directed communities for readers. While you can interact seamlessly with users anywhere in the BookWyrm network, this community is unique."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:45
+#, python-format
+msgid "%(title)s is %(site_name)s's most beloved book, with an average rating of %(rating)s out of 5."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:64
+#, python-format
+msgid "More %(site_name)s users want to read %(title)s than any other book."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:83
+#, python-format
+msgid "%(title)s has the most divisive ratings of any book on %(site_name)s."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:94
+msgid "Track your reading, talk about books, write reviews, and discover what to read next. Always ad-free, anti-corporate, and community-oriented, BookWyrm is human-scale software, designed to stay small and personal. If you have feature requests, bug reports, or grand dreams, reach out and make yourself heard."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:105
+msgid "Meet your admins"
+msgstr "여기 관리자 만나기"
+
+#: bookwyrm/templates/about/about.html:108
+#, python-format
+msgid "%(site_name)s's moderators and administrators keep the site up and running, enforce the code of conduct, and respond when users report spam and bad behavior."
+msgstr ""
+
+#: bookwyrm/templates/about/about.html:122
+msgid "Moderator"
+msgstr "중재자"
+
+#: bookwyrm/templates/about/about.html:124 bookwyrm/templates/user_menu.html:62
+msgid "Admin"
+msgstr "관리"
+
+#: bookwyrm/templates/about/about.html:140
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:28
+#: bookwyrm/templates/snippets/status/status_options.html:35
+#: bookwyrm/templates/snippets/user_options.html:14
+msgid "Send direct message"
+msgstr "디렉트 메시지 보내기"
+
+#: bookwyrm/templates/about/conduct.html:4
+#: bookwyrm/templates/about/conduct.html:9
+#: bookwyrm/templates/about/layout.html:41
+#: bookwyrm/templates/snippets/footer.html:27
+msgid "Code of Conduct"
+msgstr "행동 지침"
+
+#: bookwyrm/templates/about/impressum.html:4
+#: bookwyrm/templates/about/impressum.html:9
+#: bookwyrm/templates/about/layout.html:54
+#: bookwyrm/templates/snippets/footer.html:34
+msgid "Impressum"
+msgstr "법률 고지"
+
+#: bookwyrm/templates/about/layout.html:11
+msgid "Active users:"
+msgstr "활성 이용자"
+
+#: bookwyrm/templates/about/layout.html:15
+msgid "Statuses posted:"
+msgstr "게시한 기록:"
+
+#: bookwyrm/templates/about/layout.html:19
+#: bookwyrm/templates/setup/config.html:74
+msgid "Software version:"
+msgstr "소프트웨어 버전:"
+
+#: bookwyrm/templates/about/layout.html:30
+#: bookwyrm/templates/embed-layout.html:34
+#: bookwyrm/templates/snippets/footer.html:8
+#, python-format
+msgid "About %(site_name)s"
+msgstr "%(site_name)s에 관하여"
+
+#: bookwyrm/templates/about/layout.html:47
+#: bookwyrm/templates/about/privacy.html:4
+#: bookwyrm/templates/about/privacy.html:9
+#: bookwyrm/templates/snippets/footer.html:30
+msgid "Privacy Policy"
+msgstr "개인정보처리방침"
+
+#: bookwyrm/templates/annual_summary/layout.html:7
+#: bookwyrm/templates/feed/summary_card.html:8
+#, python-format
+msgid "%(year)s in the books"
+msgstr "%(year)s년의 책들"
+
+#: bookwyrm/templates/annual_summary/layout.html:43
+#, python-format
+msgid "%(year)s in the books"
+msgstr "%(year)s년의 책들"
+
+#: bookwyrm/templates/annual_summary/layout.html:47
+#, python-format
+msgid "%(display_name)s’s year of reading"
+msgstr "%(display_name)s의 올 해 독서"
+
+#: bookwyrm/templates/annual_summary/layout.html:53
+msgid "Share this page"
+msgstr "이 페이지 공유"
+
+#: bookwyrm/templates/annual_summary/layout.html:67
+msgid "Copy address"
+msgstr "주소 복사"
+
+#: bookwyrm/templates/annual_summary/layout.html:68
+#: bookwyrm/templates/lists/list.html:277
+msgid "Copied!"
+msgstr "복사함!"
+
+#: bookwyrm/templates/annual_summary/layout.html:77
+msgid "Sharing status: public with key"
+msgstr ""
+
+#: bookwyrm/templates/annual_summary/layout.html:78
+msgid "The page can be seen by anyone with the complete address."
+msgstr ""
+
+#: bookwyrm/templates/annual_summary/layout.html:83
+msgid "Make page private"
+msgstr "페이지 비공개하기"
+
+#: bookwyrm/templates/annual_summary/layout.html:89
+msgid "Sharing status: private"
+msgstr ""
+
+#: bookwyrm/templates/annual_summary/layout.html:90
+msgid "The page is private, only you can see it."
+msgstr "이 페이지는 비공개이므로 자신만 볼 수 있어요."
+
+#: bookwyrm/templates/annual_summary/layout.html:95
+msgid "Make page public"
+msgstr "페이지 공개하기"
+
+#: bookwyrm/templates/annual_summary/layout.html:99
+msgid "When you make your page private, the old key won’t give access to the page anymore. A new key will be created if the page is once again made public."
+msgstr ""
+
+#: bookwyrm/templates/annual_summary/layout.html:112
+#, python-format
+msgid "Sadly %(display_name)s didn’t finish any books in %(year)s"
+msgstr ""
+
+#: bookwyrm/templates/annual_summary/layout.html:118
+#, python-format
+msgid "In %(year)s, %(display_name)s read %(books_total)s book%(link_url)s
.%(confirmation_code)s
\" at login."
+msgstr ""
+
+#: bookwyrm/templates/email/confirm/subject.html:2
+msgid "Please confirm your email"
+msgstr "이메일 주소 확인하기"
+
+#: bookwyrm/templates/email/confirm/text_content.html:10
+#, python-format
+msgid "Or enter the code \"%(confirmation_code)s\" at login."
+msgstr ""
+
+#: bookwyrm/templates/email/html_layout.html:15
+#: bookwyrm/templates/email/text_layout.html:2
+msgid "Hi there,"
+msgstr ""
+
+#: bookwyrm/templates/email/html_layout.html:21
+#, python-format
+msgid "BookWyrm hosted on %(site_name)s"
+msgstr "%(site_name)s에서 호스트하는 BookWyrm"
+
+#: bookwyrm/templates/email/html_layout.html:23
+msgid "Email preference"
+msgstr "이메일 설정"
+
+#: bookwyrm/templates/email/invite/html_content.html:6
+#: bookwyrm/templates/email/invite/subject.html:2
+#, python-format
+msgid "You're invited to join %(site_name)s!"
+msgstr ""
+
+#: bookwyrm/templates/email/invite/html_content.html:9
+msgid "Join Now"
+msgstr "바로 참여하기"
+
+#: bookwyrm/templates/email/invite/html_content.html:15
+#, python-format
+msgid "Learn more about %(site_name)s."
+msgstr ""
+
+#: bookwyrm/templates/email/invite/text_content.html:4
+#, python-format
+msgid "You're invited to join %(site_name)s! Click the link below to create an account."
+msgstr ""
+
+#: bookwyrm/templates/email/invite/text_content.html:8
+#, python-format
+msgid "Learn more about %(site_name)s:"
+msgstr ""
+
+#: bookwyrm/templates/email/moderation_report/html_content.html:8
+#: bookwyrm/templates/email/moderation_report/text_content.html:6
+#, python-format
+msgid "@%(reporter)s has flagged a link domain for moderation."
+msgstr ""
+
+#: bookwyrm/templates/email/moderation_report/html_content.html:14
+#: bookwyrm/templates/email/moderation_report/text_content.html:10
+#, python-format
+msgid "@%(reporter)s has flagged behavior by @%(reportee)s for moderation."
+msgstr ""
+
+#: bookwyrm/templates/email/moderation_report/html_content.html:21
+#: bookwyrm/templates/email/moderation_report/text_content.html:15
+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/text_content.html:4
+#, python-format
+msgid "You requested to reset your %(site_name)s password. Click the link below to set a new password and log in to your account."
+msgstr ""
+
+#: bookwyrm/templates/email/password_reset/html_content.html:9
+#: bookwyrm/templates/landing/password_reset.html:4
+#: bookwyrm/templates/landing/password_reset.html:10
+#: bookwyrm/templates/landing/password_reset_request.html:4
+#: bookwyrm/templates/landing/password_reset_request.html:10
+msgid "Reset Password"
+msgstr "암호 재설정"
+
+#: bookwyrm/templates/email/password_reset/html_content.html:13
+#: bookwyrm/templates/email/password_reset/text_content.html:8
+msgid "If you didn't request to reset your password, you can ignore this email."
+msgstr ""
+
+#: bookwyrm/templates/email/password_reset/subject.html:2
+#, python-format
+msgid "Reset your %(site_name)s password"
+msgstr ""
+
+#: bookwyrm/templates/email/test/html_content.html:6
+#: bookwyrm/templates/email/test/text_content.html:4
+msgid "This is a test email."
+msgstr "시험 이메일입니다."
+
+#: bookwyrm/templates/email/test/subject.html:2
+msgid "Test email"
+msgstr "시험 이메일"
+
+#: bookwyrm/templates/embed-layout.html:21 bookwyrm/templates/layout.html:33
+#: bookwyrm/templates/layout.html:163 bookwyrm/templates/setup/layout.html:15
+#: bookwyrm/templates/two_factor_auth/two_factor_login.html:18
+#: bookwyrm/templates/two_factor_auth/two_factor_prompt.html:18
+#, python-format
+msgid "%(site_name)s home page"
+msgstr ""
+
+#: bookwyrm/templates/embed-layout.html:40
+#: bookwyrm/templates/snippets/footer.html:12
+msgid "Contact site admin"
+msgstr "사이트 관리자 연락하기"
+
+#: bookwyrm/templates/embed-layout.html:46
+msgid "Join BookWyrm"
+msgstr "BookWyrm 참여하기"
+
+#: bookwyrm/templates/feed/direct_messages.html:8
+#, python-format
+msgid "Direct Messages with %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/feed/direct_messages.html:10
+#: bookwyrm/templates/user_menu.html:39
+msgid "Direct Messages"
+msgstr "디렉트 메시지"
+
+#: bookwyrm/templates/feed/direct_messages.html:13
+msgid "All messages"
+msgstr "모든 메시지"
+
+#: bookwyrm/templates/feed/direct_messages.html:22
+msgid "You have no messages right now."
+msgstr ""
+
+#: bookwyrm/templates/feed/feed.html:55
+msgid "There aren't any activities right now! Try following a user to get started"
+msgstr ""
+
+#: bookwyrm/templates/feed/feed.html:56
+msgid "Alternatively, you can try enabling more status types"
+msgstr ""
+
+#: bookwyrm/templates/feed/goal_card.html:6
+#: bookwyrm/templates/feed/layout.html:14
+#: bookwyrm/templates/user/goal_form.html:6
+#, python-format
+msgid "%(year)s Reading Goal"
+msgstr "%(year)s 읽기 목표"
+
+#: bookwyrm/templates/feed/goal_card.html:18
+#, python-format
+msgid "You can set or change your reading goal any time from your profile page"
+msgstr ""
+
+#: bookwyrm/templates/feed/layout.html:4
+msgid "Updates"
+msgstr "업데이트"
+
+#: bookwyrm/templates/feed/suggested_books.html:6
+#: bookwyrm/templates/guided_tour/home.html:127
+#: bookwyrm/templates/layout.html:94
+msgid "Your Books"
+msgstr "내 도서"
+
+#: bookwyrm/templates/feed/suggested_books.html:10
+msgid "There are no books here right now! Try searching for a book to get started"
+msgstr ""
+
+#: bookwyrm/templates/feed/suggested_books.html:13
+msgid "Do you have book data from another service like GoodReads?"
+msgstr ""
+
+#: bookwyrm/templates/feed/suggested_books.html:16
+msgid "Import your reading history"
+msgstr "내가 읽은 내역 가져오기"
+
+#: bookwyrm/templates/feed/suggested_users.html:5
+#: bookwyrm/templates/get_started/users.html:6
+msgid "Who to follow"
+msgstr "팔로우할 만한 이"
+
+#: bookwyrm/templates/feed/suggested_users.html:9
+msgid "Don't show suggested users"
+msgstr "추천 이용자 보지 않음"
+
+#: bookwyrm/templates/feed/suggested_users.html:14
+msgid "View directory"
+msgstr "디렉터리 보기"
+
+#: bookwyrm/templates/feed/summary_card.html:21
+msgid "The end of the year is the best moment to take stock of all the books read during the last 12 months. How many pages have you read? Which book is your best-rated of the year? We compiled these stats, and more!"
+msgstr "연말은 지난 12개월 동안 읽은 모든 책을 점검하기에 가장 좋은 시기입니다. 몇 쪽이나 읽었나요? 올해 가장 높은 평점을 준 책은 무엇인가요? 이러한 통계 등을 정리해 보았습니다!"
+
+#: bookwyrm/templates/feed/summary_card.html:26
+#, python-format
+msgid "Discover your stats for %(year)s!"
+msgstr ""
+
+#: bookwyrm/templates/get_started/book_preview.html:6
+#, python-format
+msgid "Have you read %(book_title)s?"
+msgstr "%(book_title)s 읽어보았나요?"
+
+#: bookwyrm/templates/get_started/book_preview.html:7
+msgid "Add to your books"
+msgstr "내 도서 추가"
+
+#: bookwyrm/templates/get_started/book_preview.html:10
+#: bookwyrm/templates/shelf/shelf.html:88 bookwyrm/templates/user/user.html:37
+#: bookwyrm/templatetags/shelf_tags.py:14
+msgid "To Read"
+msgstr "읽을 것"
+
+#: bookwyrm/templates/get_started/book_preview.html:11
+#: bookwyrm/templates/shelf/shelf.html:89 bookwyrm/templates/user/user.html:38
+#: bookwyrm/templatetags/shelf_tags.py:15
+msgid "Currently Reading"
+msgstr "읽는 중"
+
+#: bookwyrm/templates/get_started/book_preview.html:12
+#: bookwyrm/templates/shelf/shelf.html:90
+#: bookwyrm/templates/snippets/shelf_selector.html:46
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:24
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12
+#: bookwyrm/templates/user/user.html:39 bookwyrm/templatetags/shelf_tags.py:16
+msgid "Read"
+msgstr "읽음"
+
+#: bookwyrm/templates/get_started/book_preview.html:13
+#: bookwyrm/templates/shelf/shelf.html:91 bookwyrm/templates/user/user.html:40
+#: bookwyrm/templatetags/shelf_tags.py:17
+msgid "Stopped Reading"
+msgstr "읽다 멈춘 것"
+
+#: bookwyrm/templates/get_started/books.html:6
+msgid "What are you reading?"
+msgstr "무엇을 읽고 있나요?"
+
+#: bookwyrm/templates/get_started/books.html:9
+#: bookwyrm/templates/layout.html:41 bookwyrm/templates/lists/list.html:213
+msgid "Search for a book"
+msgstr "도서 검색"
+
+#: bookwyrm/templates/get_started/books.html:11
+#, python-format
+msgid "No books found for \"%(query)s\""
+msgstr ""
+
+#: bookwyrm/templates/get_started/books.html:11
+#, python-format
+msgid "You can add books when you start using %(site_name)s."
+msgstr ""
+
+#: bookwyrm/templates/get_started/books.html:16
+#: bookwyrm/templates/get_started/books.html:17
+#: bookwyrm/templates/get_started/users.html:18
+#: bookwyrm/templates/get_started/users.html:19
+#: bookwyrm/templates/groups/members.html:15
+#: bookwyrm/templates/groups/members.html:16 bookwyrm/templates/layout.html:47
+#: bookwyrm/templates/layout.html:48 bookwyrm/templates/lists/list.html:217
+#: bookwyrm/templates/search/layout.html:5
+#: bookwyrm/templates/search/layout.html:10
+#: bookwyrm/templates/search/layout.html:32
+msgid "Search"
+msgstr "검색"
+
+#: bookwyrm/templates/get_started/books.html:27
+msgid "Suggested Books"
+msgstr "추천 도서"
+
+#: bookwyrm/templates/get_started/books.html:33
+msgid "Search results"
+msgstr "검색 결과"
+
+#: bookwyrm/templates/get_started/books.html:46
+#, python-format
+msgid "Popular on %(site_name)s"
+msgstr ""
+
+#: bookwyrm/templates/get_started/books.html:58
+#: bookwyrm/templates/lists/list.html:230
+msgid "No books found"
+msgstr "도서를 찾을 수 없음"
+
+#: bookwyrm/templates/get_started/books.html:63
+#: bookwyrm/templates/get_started/profile.html:64
+msgid "Save & continue"
+msgstr "저장 & 계속하기"
+
+#: bookwyrm/templates/get_started/layout.html:5
+#: bookwyrm/templates/landing/layout.html:5
+msgid "Welcome"
+msgstr "환영"
+
+#: bookwyrm/templates/get_started/layout.html:24
+msgid "These are some first steps to get you started."
+msgstr ""
+
+#: bookwyrm/templates/get_started/layout.html:38
+#: bookwyrm/templates/get_started/profile.html:6
+msgid "Create your profile"
+msgstr "내 프로필 만들기"
+
+#: bookwyrm/templates/get_started/layout.html:42
+msgid "Add books"
+msgstr "도서 추가"
+
+#: bookwyrm/templates/get_started/layout.html:46
+msgid "Find friends"
+msgstr "친구 찾기"
+
+#: bookwyrm/templates/get_started/layout.html:52
+msgid "Skip this step"
+msgstr "이 과정을 생략"
+
+#: bookwyrm/templates/get_started/layout.html:56
+#: bookwyrm/templates/guided_tour/group.html:101
+msgid "Finish"
+msgstr "끝내기"
+
+#: bookwyrm/templates/get_started/profile.html:15
+#: bookwyrm/templates/preferences/edit_user.html:41
+msgid "Display name:"
+msgstr "나타낼 이름:"
+
+#: bookwyrm/templates/get_started/profile.html:29
+#: bookwyrm/templates/preferences/edit_user.html:47
+#: bookwyrm/templates/settings/announcements/edit_announcement.html:49
+msgid "Summary:"
+msgstr "요약:"
+
+#: bookwyrm/templates/get_started/profile.html:34
+msgid "A little bit about you"
+msgstr ""
+
+#: bookwyrm/templates/get_started/profile.html:43
+#: bookwyrm/templates/preferences/edit_user.html:27
+msgid "Avatar:"
+msgstr "아바타:"
+
+#: bookwyrm/templates/get_started/profile.html:52
+msgid "Manually approve followers:"
+msgstr "수동으로 팔로워 승인:"
+
+#: bookwyrm/templates/get_started/profile.html:58
+msgid "Show this account in suggested users:"
+msgstr "이 계정을 추천 이용자에 보이기:"
+
+#: bookwyrm/templates/get_started/profile.html:62
+msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users."
+msgstr ""
+
+#: bookwyrm/templates/get_started/users.html:8
+msgid "You can follow users on other BookWyrm instances and federated services like Mastodon."
+msgstr ""
+
+#: bookwyrm/templates/get_started/users.html:11
+msgid "Search for a user"
+msgstr "이용자 검색"
+
+#: bookwyrm/templates/get_started/users.html:13
+#, python-format
+msgid "No users found for \"%(query)s\""
+msgstr ""
+
+#: bookwyrm/templates/groups/create_form.html:5
+#: bookwyrm/templates/guided_tour/user_groups.html:32
+#: bookwyrm/templates/user/groups.html:22
+msgid "Create group"
+msgstr "그룹 만들기"
+
+#: bookwyrm/templates/groups/created_text.html:4
+#, python-format
+msgid "Managed by %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/groups/delete_group_modal.html:4
+msgid "Delete this group?"
+msgstr "이 그룹을 없앨까요?"
+
+#: bookwyrm/templates/groups/delete_group_modal.html:7
+#: bookwyrm/templates/lists/delete_list_modal.html:7
+#: bookwyrm/templates/readthrough/delete_readthrough_modal.html:12
+#: bookwyrm/templates/settings/imports/complete_import_modal.html:7
+msgid "This action cannot be un-done"
+msgstr "이 행동은 되돌릴 수 없어요."
+
+#: bookwyrm/templates/groups/delete_group_modal.html:17
+#: bookwyrm/templates/lists/delete_list_modal.html:19
+#: bookwyrm/templates/readthrough/delete_readthrough_modal.html:29
+#: bookwyrm/templates/settings/announcements/announcement.html:23
+#: bookwyrm/templates/settings/announcements/announcements.html:56
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:49
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:36
+#: bookwyrm/templates/snippets/follow_request_buttons.html:12
+#: bookwyrm/templates/snippets/join_invitation_buttons.html:14
+msgid "Delete"
+msgstr "지우기"
+
+#: bookwyrm/templates/groups/edit_form.html:5
+msgid "Edit Group"
+msgstr "그룹 편집"
+
+#: bookwyrm/templates/groups/form.html:8
+msgid "Group Name:"
+msgstr "그룹 이름:"
+
+#: bookwyrm/templates/groups/form.html:12
+msgid "Group Description:"
+msgstr "그룹 설명:"
+
+#: bookwyrm/templates/groups/form.html:21
+msgid "Delete group"
+msgstr "그룹 지우기"
+
+#: bookwyrm/templates/groups/group.html:21
+msgid "Members of this group can create group-curated lists."
+msgstr "이 그룹의 구성원은 그룹선정목록을 만들 수 있습니다."
+
+#: bookwyrm/templates/groups/group.html:26
+#: bookwyrm/templates/lists/create_form.html:5
+#: bookwyrm/templates/lists/lists.html:20
+msgid "Create List"
+msgstr "목록 만들기"
+
+#: bookwyrm/templates/groups/group.html:39
+msgid "This group has no lists"
+msgstr "이 그룹에는 목록이 없습니다."
+
+#: bookwyrm/templates/groups/layout.html:17
+msgid "Edit group"
+msgstr "그룹 편집"
+
+#: bookwyrm/templates/groups/members.html:11
+msgid "Search to add a user"
+msgstr "검색하여 이용자 추가하기"
+
+#: bookwyrm/templates/groups/members.html:32
+msgid "Leave group"
+msgstr "그룹 떠나기"
+
+#: bookwyrm/templates/groups/members.html:54
+#: bookwyrm/templates/groups/suggested_users.html:35
+#: bookwyrm/templates/snippets/suggested_users.html:31
+#: bookwyrm/templates/user/user_preview.html:39
+#: bookwyrm/templates/user/user_preview.html:47
+msgid "Follows you"
+msgstr "나를 팔로우"
+
+#: bookwyrm/templates/groups/suggested_users.html:7
+msgid "Add new members!"
+msgstr "새 구성원 추가하기!"
+
+#: bookwyrm/templates/groups/suggested_users.html:20
+#: bookwyrm/templates/snippets/suggested_users.html:16
+#, python-format
+msgid "%(mutuals)s follower you follow"
+msgid_plural "%(mutuals)s followers you follow"
+msgstr[0] ""
+
+#: bookwyrm/templates/groups/suggested_users.html:27
+#: bookwyrm/templates/snippets/suggested_users.html:23
+#, python-format
+msgid "%(shared_books)s book on your shelves"
+msgid_plural "%(shared_books)s books on your shelves"
+msgstr[0] ""
+
+#: bookwyrm/templates/groups/suggested_users.html:43
+#, python-format
+msgid "No potential members found for \"%(user_query)s\""
+msgstr ""
+
+#: bookwyrm/templates/groups/user_groups.html:15
+msgid "Manager"
+msgstr "매니저"
+
+#: bookwyrm/templates/groups/user_groups.html:35
+msgid "No groups found."
+msgstr "그룹이 없습니다."
+
+#: bookwyrm/templates/guided_tour/book.html:10
+msgid "This is home page of a book. Let's see what you can do while you're here!"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:11
+msgid "Book page"
+msgstr "책 페이지"
+
+#: bookwyrm/templates/guided_tour/book.html:19
+#: bookwyrm/templates/guided_tour/group.html:19
+#: bookwyrm/templates/guided_tour/lists.html:22
+#: bookwyrm/templates/guided_tour/search.html:29
+#: bookwyrm/templates/guided_tour/search.html:56
+#: bookwyrm/templates/guided_tour/user_books.html:19
+#: bookwyrm/templates/guided_tour/user_groups.html:19
+#: bookwyrm/templates/guided_tour/user_profile.html:19
+msgid "End Tour"
+msgstr "투어 끝내기"
+
+#: bookwyrm/templates/guided_tour/book.html:26
+#: bookwyrm/templates/guided_tour/book.html:50
+#: bookwyrm/templates/guided_tour/book.html:74
+#: bookwyrm/templates/guided_tour/book.html:97
+#: bookwyrm/templates/guided_tour/book.html:122
+#: bookwyrm/templates/guided_tour/book.html:146
+#: bookwyrm/templates/guided_tour/book.html:170
+#: bookwyrm/templates/guided_tour/book.html:194
+#: bookwyrm/templates/guided_tour/book.html:219
+#: bookwyrm/templates/guided_tour/book.html:243
+#: bookwyrm/templates/guided_tour/book.html:268
+#: bookwyrm/templates/guided_tour/book.html:274
+#: bookwyrm/templates/guided_tour/group.html:26
+#: bookwyrm/templates/guided_tour/group.html:49
+#: bookwyrm/templates/guided_tour/group.html:72
+#: bookwyrm/templates/guided_tour/group.html:95
+#: bookwyrm/templates/guided_tour/home.html:74
+#: bookwyrm/templates/guided_tour/home.html:97
+#: bookwyrm/templates/guided_tour/home.html:121
+#: bookwyrm/templates/guided_tour/home.html:146
+#: bookwyrm/templates/guided_tour/home.html:171
+#: bookwyrm/templates/guided_tour/home.html:195
+#: bookwyrm/templates/guided_tour/lists.html:29
+#: bookwyrm/templates/guided_tour/lists.html:53
+#: bookwyrm/templates/guided_tour/lists.html:76
+#: bookwyrm/templates/guided_tour/lists.html:100
+#: bookwyrm/templates/guided_tour/lists.html:123
+#: bookwyrm/templates/guided_tour/search.html:36
+#: bookwyrm/templates/guided_tour/search.html:63
+#: bookwyrm/templates/guided_tour/search.html:89
+#: bookwyrm/templates/guided_tour/search.html:116
+#: bookwyrm/templates/guided_tour/search.html:140
+#: bookwyrm/templates/guided_tour/user_books.html:26
+#: bookwyrm/templates/guided_tour/user_books.html:50
+#: bookwyrm/templates/guided_tour/user_books.html:73
+#: bookwyrm/templates/guided_tour/user_books.html:96
+#: bookwyrm/templates/guided_tour/user_groups.html:26
+#: bookwyrm/templates/guided_tour/user_groups.html:50
+#: bookwyrm/templates/guided_tour/user_groups.html:73
+#: bookwyrm/templates/guided_tour/user_groups.html:97
+#: bookwyrm/templates/guided_tour/user_profile.html:26
+#: bookwyrm/templates/guided_tour/user_profile.html:49
+#: bookwyrm/templates/guided_tour/user_profile.html:72
+#: bookwyrm/templates/guided_tour/user_profile.html:95
+#: bookwyrm/templates/guided_tour/user_profile.html:118
+#: bookwyrm/templates/snippets/pagination.html:30
+msgid "Next"
+msgstr "다음"
+
+#: bookwyrm/templates/guided_tour/book.html:31
+msgid "This is where you can set a reading status for this book. You can press the button to move to the next stage, or use the drop down button to select the reading status you want to set."
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:32
+msgid "Reading status"
+msgstr "읽은 기록"
+
+#: bookwyrm/templates/guided_tour/book.html:55
+msgid "You can also manually add reading dates here. Unlike changing the reading status using the previous method, adding dates manually will not automatically add them to your Read or Reading shelves."
+msgstr "여기에서 읽은 날짜를 직접 추가할 수도 있습니다. 앞서 설명한 방법으로 읽기 상태를 변경하는 것과 달리 수동으로 날짜를 추가해도 읽음 또는 읽는 중 책꽂이에 자동으로 추가되지 않습니다."
+
+#: bookwyrm/templates/guided_tour/book.html:55
+msgid "Got a favourite you re-read every year? We've got you covered - you can add multiple read dates for the same book 😀"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:79
+msgid "There can be multiple editions of a book, in various formats or languages. You can choose which edition you want to use."
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:80
+msgid "Other editions"
+msgstr "그 밖의 판"
+
+#: bookwyrm/templates/guided_tour/book.html:102
+msgid "You can post a review, comment, or quote here."
+msgstr "이곳에서 서평, 해설, 인용을 게시할 수 있어요."
+
+#: bookwyrm/templates/guided_tour/book.html:103
+msgid "Share your thoughts"
+msgstr "함께 사유하기"
+
+#: bookwyrm/templates/guided_tour/book.html:127
+msgid "If you have read this book you can post a review including an optional star rating"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:128
+msgid "Post a review"
+msgstr "서펑 게시하기"
+
+#: bookwyrm/templates/guided_tour/book.html:151
+msgid "You can share your thoughts on this book generally with a simple comment"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:152
+msgid "Post a comment"
+msgstr "코멘트 발행하기"
+
+#: bookwyrm/templates/guided_tour/book.html:175
+msgid "Just read some perfect prose? Let the world know by sharing a quote!"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:176
+msgid "Share a quote"
+msgstr "인용 공유하기"
+
+#: bookwyrm/templates/guided_tour/book.html:199
+msgid "If your review or comment might ruin the book for someone who hasn't read it yet, you can hide your post behind a spoiler alert"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:200
+msgid "Spoiler alerts"
+msgstr "스포일러 경고"
+
+#: bookwyrm/templates/guided_tour/book.html:224
+msgid "Choose who can see your post here. Post privacy can be Public (everyone can see), Unlisted (everyone can see, but it doesn't appear in public feeds or discovery pages), Followers (only your followers can see), or Private (only you can see)"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:225
+#: bookwyrm/templates/snippets/privacy_select.html:6
+#: bookwyrm/templates/snippets/privacy_select_no_followers.html:6
+msgid "Post privacy"
+msgstr "게시물 개인정보처리"
+
+#: bookwyrm/templates/guided_tour/book.html:248
+msgid "Some ebooks can be downloaded for free from external sources. They will be shown here."
+msgstr "어떤 전자책은 외부 출처에서 무료로 내려받을 수 있어요. 여기에 나타납니다."
+
+#: bookwyrm/templates/guided_tour/book.html:249
+msgid "Download links"
+msgstr "내려받기 링크"
+
+#: bookwyrm/templates/guided_tour/book.html:273
+msgid "Continue the tour by selecting Your books from the drop down menu."
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/book.html:296
+#: bookwyrm/templates/guided_tour/home.html:50
+#: bookwyrm/templates/guided_tour/home.html:218
+#: bookwyrm/templates/guided_tour/search.html:161
+#: bookwyrm/templates/guided_tour/user_books.html:124
+#: bookwyrm/templates/guided_tour/user_groups.html:116
+#: bookwyrm/templates/guided_tour/user_profile.html:141
+msgid "Ok"
+msgstr "알겠어요"
+
+#: bookwyrm/templates/guided_tour/group.html:10
+msgid "Welcome to the page for your group! This is where you can add and remove users, create user-curated lists, and edit the group details."
+msgstr "그룹 페이지에 방문하셨습니다! 이 곳에서는 이용자를 더하거나 뺄 수 있고, 이용자 선정 목록을 만들고, 그룹 세부사항도 변경할 수 있습니다."
+
+#: bookwyrm/templates/guided_tour/group.html:11
+msgid "Your group"
+msgstr "내 그룹"
+
+#: bookwyrm/templates/guided_tour/group.html:31
+msgid "Use this search box to find users to join your group. Currently users must be members of the same Bookwyrm instance and be invited by the group owner."
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/group.html:32
+msgid "Find users"
+msgstr "이용자 찾기"
+
+#: bookwyrm/templates/guided_tour/group.html:54
+msgid "Your group members will appear here. The group owner is marked with a star symbol."
+msgstr "그룹 구성원이 여기에 표시됩니다. 그룹 소유자에게는 별 기호가 표시됩니다."
+
+#: bookwyrm/templates/guided_tour/group.html:55
+msgid "Group members"
+msgstr "그룹 구성원"
+
+#: bookwyrm/templates/guided_tour/group.html:77
+msgid "As well as creating lists from the Lists page, you can create a group-curated list here on the group's homepage. Any member of the group can create a list curated by group members."
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/group.html:78
+msgid "Group lists"
+msgstr "그룹 목록"
+
+#: bookwyrm/templates/guided_tour/group.html:100
+msgid "Congratulations, you've finished the tour! Now you know the basics, but there is lots more to explore on your own. Happy reading!"
+msgstr ""
+
+#: bookwyrm/templates/guided_tour/group.html:115
+msgid "End tour"
+msgstr "투어 끝내기"
+
+#: bookwyrm/templates/guided_tour/home.html:16
+msgid "Welcome to Bookwyrm!.tar.gz
."
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:58
+msgid "Step 2:"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:60
+msgid "Deselect any checkboxes for data you do not wish to include in your import."
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:71
+#: bookwyrm/templates/shelf/shelf.html:26
+#: bookwyrm/templates/user/relationships/followers.html:18
+#: bookwyrm/templates/user/relationships/following.html:18
+msgid "User profile"
+msgstr "이용자 프로필"
+
+#: bookwyrm/templates/import/import_user.html:74
+msgid "Overwrites display name, summary, and avatar"
+msgstr "나타낼 이름과 요약, 아바타를 덮어쓰기"
+
+#: bookwyrm/templates/import/import_user.html:80
+msgid "User settings"
+msgstr "이용자 설정"
+
+#: bookwyrm/templates/import/import_user.html:83
+msgid "Overwrites:"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:86
+msgid "Whether manual approval is required for other users to follow your account"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:89
+msgid "Whether following/followers are shown on your profile"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:92
+msgid "Whether your reading goal is shown on your profile"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:95
+msgid "Whether you see user follow suggestions"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:98
+msgid "Whether your account is suggested to others"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:101
+msgid "Your timezone"
+msgstr "내 시간대"
+
+#: bookwyrm/templates/import/import_user.html:104
+msgid "Your default post privacy setting"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:112
+msgid "Followers and following"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:116
+msgid "User blocks"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:123
+msgid "Reading goals"
+msgstr "읽기 목표"
+
+#: bookwyrm/templates/import/import_user.html:126
+msgid "Overwrites reading goals for all years listed in the import file"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:130
+msgid "Shelves"
+msgstr "책꽂이"
+
+#: bookwyrm/templates/import/import_user.html:133
+msgid "Reading history"
+msgstr "읽은 내역"
+
+#: bookwyrm/templates/import/import_user.html:136
+msgid "Book reviews"
+msgstr "책 평가"
+
+#: bookwyrm/templates/import/import_user.html:142
+msgid "Comments about books"
+msgstr ""
+
+#: bookwyrm/templates/import/import_user.html:145
+msgid "Book lists"
+msgstr "책 목록"
+
+#: bookwyrm/templates/import/import_user.html:148
+msgid "Saved lists"
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:5
+#: bookwyrm/templates/import/troubleshoot.html:4
+msgid "Import Troubleshooting"
+msgstr "가져오기 문제해결"
+
+#: 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."
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:58
+#: bookwyrm/templates/lists/curate.html:71
+#: bookwyrm/templates/settings/link_domains/link_domains.html:76
+msgid "Approve"
+msgstr "승인하기"
+
+#: bookwyrm/templates/import/manual_review.html:66
+msgid "Reject"
+msgstr "거절"
+
+#: bookwyrm/templates/import/troubleshoot.html:7
+#: bookwyrm/templates/settings/imports/imports.html:171
+msgid "Failed items"
+msgstr "실패한 항목"
+
+#: bookwyrm/templates/import/troubleshoot.html:12
+msgid "Troubleshooting"
+msgstr "문제해결"
+
+#: bookwyrm/templates/import/troubleshoot.html:20
+msgid "Re-trying an import can fix missing items in cases such as:"
+msgstr "가져오기를 다시 시도하면 다음의 경우에 누락된 항목이 수정될 수 있습니다."
+
+#: bookwyrm/templates/import/troubleshoot.html:23
+msgid "The book has been added to the instance since this import"
+msgstr "이 가져오기 이후 책이 서버에 추가된 경우."
+
+#: bookwyrm/templates/import/troubleshoot.html:24
+msgid "A transient error or timeout caused the external data source to be unavailable."
+msgstr "일시적인 오류 또는 시간 초과로 인해 외부 데이터 소스를 사용할 수 없었던 경우."
+
+#: bookwyrm/templates/import/troubleshoot.html:25
+msgid "BookWyrm has been updated since this import with a bug fix"
+msgstr "이 가져오기 이후 BookWyrm이 버그 수정과 함께 업데이트된 경우."
+
+#: bookwyrm/templates/import/troubleshoot.html:28
+msgid "Contact your admin or open an issue if you are seeing unexpected failed items."
+msgstr "예상치 못한 실패 항목이 표시되는 경우에는 관리자에게 문의하거나 이슈를 열어주세요."
+
+#: bookwyrm/templates/landing/invite.html:4
+#: bookwyrm/templates/landing/invite.html:8
+#: bookwyrm/templates/landing/login.html:48
+#: bookwyrm/templates/landing/reactivate.html:41
+msgid "Create an Account"
+msgstr "계정 만들기"
+
+#: bookwyrm/templates/landing/invite.html:22
+msgid "Sorry! This invite code is no longer valid."
+msgstr ""
+
+#: bookwyrm/templates/landing/landing.html:9
+msgid "Recent Books"
+msgstr "최근 도서"
+
+#: bookwyrm/templates/landing/layout.html:17
+msgid "Decentralized"
+msgstr "탈중앙화"
+
+#: bookwyrm/templates/landing/layout.html:23
+msgid "Friendly"
+msgstr "친근함"
+
+#: bookwyrm/templates/landing/layout.html:29
+msgid "Anti-Corporate"
+msgstr "반기업"
+
+#: bookwyrm/templates/landing/layout.html:46
+#, python-format
+msgid "Join %(name)s"
+msgstr "%(name)s 서버에서 참여하기"
+
+#: bookwyrm/templates/landing/layout.html:48
+msgid "Request an Invitation"
+msgstr "초대장 요청하기"
+
+#: bookwyrm/templates/landing/layout.html:50
+#, python-format
+msgid "%(name)s registration is closed"
+msgstr ""
+
+#: bookwyrm/templates/landing/layout.html:61
+msgid "Thank you! Your request has been received."
+msgstr ""
+
+#: bookwyrm/templates/landing/layout.html:90
+msgid "Your Account"
+msgstr "내 계정"
+
+#: bookwyrm/templates/landing/login.html:4
+msgid "Login"
+msgstr "로그인"
+
+#: bookwyrm/templates/landing/login.html:7
+#: bookwyrm/templates/landing/login.html:36 bookwyrm/templates/layout.html:142
+#: bookwyrm/templates/ostatus/error.html:37
+msgid "Log in"
+msgstr "로그인"
+
+#: bookwyrm/templates/landing/login.html:15
+msgid "Success! Email address confirmed."
+msgstr "성공! 이메일 주소 확인을 마쳤습니다."
+
+#: bookwyrm/templates/landing/login.html:21
+#: bookwyrm/templates/landing/reactivate.html:17
+#: bookwyrm/templates/layout.html:128 bookwyrm/templates/ostatus/error.html:28
+#: bookwyrm/templates/snippets/register_form.html:4
+msgid "Username:"
+msgstr "이용자명:"
+
+#: bookwyrm/templates/landing/login.html:27
+#: bookwyrm/templates/landing/password_reset.html:26
+#: bookwyrm/templates/landing/reactivate.html:23
+#: bookwyrm/templates/layout.html:132 bookwyrm/templates/ostatus/error.html:32
+#: bookwyrm/templates/preferences/2fa.html:91
+#: bookwyrm/templates/snippets/register_form.html:45
+msgid "Password:"
+msgstr "암호:"
+
+#: bookwyrm/templates/landing/login.html:39 bookwyrm/templates/layout.html:139
+#: bookwyrm/templates/ostatus/error.html:34
+msgid "Forgot your password?"
+msgstr "암호를 잊었나요?"
+
+#: bookwyrm/templates/landing/login.html:61
+#: bookwyrm/templates/landing/reactivate.html:54
+msgid "More about this site"
+msgstr "이 사이트 더 알아보기"
+
+#: bookwyrm/templates/landing/password_reset.html:43
+#: bookwyrm/templates/preferences/change_password.html:33
+#: bookwyrm/templates/preferences/delete_user.html:35
+msgid "Confirm password:"
+msgstr "암호 확인:"
+
+#: bookwyrm/templates/landing/password_reset_request.html:14
+#, python-format
+msgid "A password reset link will be sent to %(email)s if there is an account using that email address."
+msgstr ""
+
+#: bookwyrm/templates/landing/password_reset_request.html:20
+msgid "A link to reset your password will be sent to your email address"
+msgstr ""
+
+#: bookwyrm/templates/landing/password_reset_request.html:34
+msgid "Reset password"
+msgstr "암호 재설정"
+
+#: bookwyrm/templates/landing/reactivate.html:4
+#: bookwyrm/templates/landing/reactivate.html:7
+msgid "Reactivate Account"
+msgstr "계정 휴면 해제하기"
+
+#: bookwyrm/templates/landing/reactivate.html:32
+msgid "Reactivate account"
+msgstr "계정 휴면 해제하기"
+
+#: bookwyrm/templates/layout.html:13
+#, python-format
+msgid "%(site_name)s search"
+msgstr ""
+
+#: bookwyrm/templates/layout.html:39
+msgid "Search for a book, user, or list"
+msgstr ""
+
+#: bookwyrm/templates/layout.html:54 bookwyrm/templates/layout.html:55
+msgid "Scan Barcode"
+msgstr "바코드 스캔하기"
+
+#: bookwyrm/templates/layout.html:69
+msgid "Main navigation menu"
+msgstr ""
+
+#: bookwyrm/templates/layout.html:134 bookwyrm/templates/ostatus/error.html:33
+msgid "password"
+msgstr "암호"
+
+#: bookwyrm/templates/layout.html:136
+msgid "Show/Hide password"
+msgstr "암호 보이기/숨기기"
+
+#: bookwyrm/templates/layout.html:150
+msgid "Join"
+msgstr "참여하기"
+
+#: bookwyrm/templates/layout.html:196
+msgid "Successfully posted status"
+msgstr ""
+
+#: bookwyrm/templates/layout.html:197
+msgid "Error posting status"
+msgstr "기록을 게시하는 중 오류가 발생했습니다."
+
+#: bookwyrm/templates/lists/add_item_modal.html:8
+#, python-format
+msgid "Add \"%(title)s\" to this list"
+msgstr ""
+
+#: bookwyrm/templates/lists/add_item_modal.html:12
+#, python-format
+msgid "Suggest \"%(title)s\" for this list"
+msgstr ""
+
+#: bookwyrm/templates/lists/add_item_modal.html:41
+#: bookwyrm/templates/lists/list.html:257
+msgid "Suggest"
+msgstr "제안사항"
+
+#: bookwyrm/templates/lists/bookmark_button.html:30
+msgid "Un-save"
+msgstr ""
+
+#: bookwyrm/templates/lists/created_text.html:5
+#, python-format
+msgid "Created by %(username)s and managed by %(groupname)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/created_text.html:7
+#, python-format
+msgid "Created and curated by %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/created_text.html:9
+#, python-format
+msgid "Created by %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:12
+msgid "Curate"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:21
+msgid "Pending Books"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:24
+msgid "You're all set!"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:45
+#: bookwyrm/templates/lists/list.html:93
+#, python-format
+msgid "%(username)s says:"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:55
+msgid "Suggested by"
+msgstr ""
+
+#: bookwyrm/templates/lists/curate.html:77
+msgid "Discard"
+msgstr "버리기"
+
+#: bookwyrm/templates/lists/delete_list_modal.html:4
+msgid "Delete this list?"
+msgstr "이 목록을 지울까요?"
+
+#: bookwyrm/templates/lists/edit_form.html:5
+#: bookwyrm/templates/lists/layout.html:23
+msgid "Edit List"
+msgstr "목록 편집"
+
+#: bookwyrm/templates/lists/embed-list.html:8
+#, python-format
+msgid "%(list_name)s, a list by %(owner)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/embed-list.html:20
+#, python-format
+msgid "on %(site_name)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/embed-list.html:29
+msgid "This list is currently empty"
+msgstr ""
+
+#: bookwyrm/templates/lists/form.html:19
+msgid "List curation:"
+msgstr "목록 큐레이션:"
+
+#: bookwyrm/templates/lists/form.html:31
+msgid "Closed"
+msgstr "닫힘"
+
+#: bookwyrm/templates/lists/form.html:34
+msgid "Only you can add and remove books to this list"
+msgstr "작성자만 이 목록에 책을 추가하고 제거할 수 있습니다."
+
+#: bookwyrm/templates/lists/form.html:48
+msgid "Curated"
+msgstr "선정"
+
+#: bookwyrm/templates/lists/form.html:51
+msgid "Anyone can suggest books, subject to your approval"
+msgstr "누구나 책을 제안할 수 있으며, 승인을 받아야 합니다."
+
+#: bookwyrm/templates/lists/form.html:65
+msgctxt "curation type"
+msgid "Open"
+msgstr "열기"
+
+#: bookwyrm/templates/lists/form.html:68
+msgid "Anyone can add books to this list"
+msgstr "누구나 이 목록에 책을 추가할 수 있습니다."
+
+#: bookwyrm/templates/lists/form.html:82
+msgid "Group"
+msgstr "그룹"
+
+#: bookwyrm/templates/lists/form.html:85
+msgid "Group members can add to and remove from this list"
+msgstr "그룹 구성원이 이 목록에 더하거나 뺄 수 있습니다."
+
+#: bookwyrm/templates/lists/form.html:90
+msgid "Select Group"
+msgstr "그룹 선택하기"
+
+#: bookwyrm/templates/lists/form.html:94
+msgid "Select a group"
+msgstr ""
+
+#: bookwyrm/templates/lists/form.html:105
+msgid "You don't have any Groups yet!"
+msgstr ""
+
+#: bookwyrm/templates/lists/form.html:107
+msgid "Create a Group"
+msgstr ""
+
+#: bookwyrm/templates/lists/form.html:121
+msgid "Delete list"
+msgstr ""
+
+#: bookwyrm/templates/lists/item_notes_field.html:7
+#: bookwyrm/templates/settings/federation/edit_instance.html:86
+msgid "Notes:"
+msgstr ""
+
+#: bookwyrm/templates/lists/item_notes_field.html:19
+msgid "An optional note that will be displayed with the book."
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:37
+msgid "That book is already on this list."
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:45
+msgid "You successfully suggested a book for this list!"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:47
+msgid "You successfully added a book to this list!"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:54
+msgid "This list is currently empty."
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:104
+msgid "Edit notes"
+msgstr "노트 편집"
+
+#: bookwyrm/templates/lists/list.html:119
+msgid "Add notes"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:131
+#, python-format
+msgid "Added by %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:146
+msgid "List position"
+msgstr "목록 위치"
+
+#: bookwyrm/templates/lists/list.html:152
+#: bookwyrm/templates/settings/link_domains/edit_domain_modal.html:23
+msgid "Set"
+msgstr "설정"
+
+#: bookwyrm/templates/lists/list.html:167
+#: bookwyrm/templates/snippets/remove_follower_button.html:4
+#: bookwyrm/templates/snippets/remove_from_group_button.html:20
+msgid "Remove"
+msgstr "제거"
+
+#: bookwyrm/templates/lists/list.html:181
+#: bookwyrm/templates/lists/list.html:198
+msgid "Sort List"
+msgstr "목록 정렬"
+
+#: bookwyrm/templates/lists/list.html:191
+msgid "Direction"
+msgstr "방향"
+
+#: bookwyrm/templates/lists/list.html:205
+msgid "Add Books"
+msgstr "책 추가하기"
+
+#: bookwyrm/templates/lists/list.html:207
+msgid "Suggest Books"
+msgstr "읽을 책 제안"
+
+#: bookwyrm/templates/lists/list.html:218
+msgid "search"
+msgstr "검색"
+
+#: bookwyrm/templates/lists/list.html:224
+msgid "Clear search"
+msgstr "검색 초기화"
+
+#: bookwyrm/templates/lists/list.html:229
+#, python-format
+msgid "No books found matching the query \"%(query)s\""
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:268
+msgid "Embed this list on a website"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:276
+msgid "Copy embed code"
+msgstr ""
+
+#: bookwyrm/templates/lists/list.html:278
+#, python-format
+msgid "%(list_name)s, a list by %(owner)s on %(site_name)s"
+msgstr ""
+
+#: bookwyrm/templates/lists/list_items.html:15
+msgid "Saved"
+msgstr "저장함"
+
+#: bookwyrm/templates/lists/list_items.html:50
+msgid "No lists found."
+msgstr "목록이 없습니다."
+
+#: bookwyrm/templates/lists/lists.html:14 bookwyrm/templates/user/lists.html:14
+msgid "Your Lists"
+msgstr "내 목록"
+
+#: bookwyrm/templates/lists/lists.html:36
+msgid "All Lists"
+msgstr "모든 목록"
+
+#: bookwyrm/templates/lists/lists.html:40
+msgid "Saved Lists"
+msgstr "저장한 목록"
+
+#: bookwyrm/templates/moved.html:27
+#, python-format
+msgid "You have moved your account to %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/moved.html:32
+msgid "You can undo the move to restore full functionality, but some followers may have already unfollowed this account."
+msgstr ""
+
+#: bookwyrm/templates/moved.html:42
+msgid "Undo move"
+msgstr ""
+
+#: bookwyrm/templates/moved.html:46 bookwyrm/templates/user_menu.html:77
+msgid "Log out"
+msgstr "로그아웃"
+
+#: bookwyrm/templates/notifications/items/accept.html:18
+#, python-format
+msgid "%(related_user)s accepted your invitation to join group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/accept.html:26
+#, python-format
+msgid "%(related_user)s and %(second_user)s accepted your invitation to join group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/accept.html:36
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others accepted your invitation to join group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:33
+#, python-format
+msgid "%(related_user)s added %(book_title)s to your list \"%(list_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:39
+#, python-format
+msgid "%(related_user)s suggested adding %(book_title)s to your list \"%(list_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:47
+#, python-format
+msgid "%(related_user)s added %(book_title)s and %(second_book_title)s to your list \"%(list_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:54
+#, python-format
+msgid "%(related_user)s suggested adding %(book_title)s and %(second_book_title)s to your list \"%(list_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:66
+#, python-format
+msgid "%(related_user)s added a book to one of your lists"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/add.html:72
+#, python-format
+msgid "%(related_user)s added %(book_title)s, %(second_book_title)s, and %(display_count)s other book to your list \"%(list_name)s\""
+msgid_plural "%(related_user)s added %(book_title)s, %(second_book_title)s, and %(display_count)s other books to your list \"%(list_name)s\""
+msgstr[0] ""
+
+#: bookwyrm/templates/notifications/items/add.html:88
+#, python-format
+msgid "%(related_user)s suggested adding %(book_title)s, %(second_book_title)s, and %(display_count)s other book to your list \"%(list_name)s\""
+msgid_plural "%(related_user)s suggested adding %(book_title)s, %(second_book_title)s, and %(display_count)s other books to your list \"%(list_name)s\""
+msgstr[0] ""
+
+#: bookwyrm/templates/notifications/items/boost.html:21
+#, python-format
+msgid "%(related_user)s boosted your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:27
+#, python-format
+msgid "%(related_user)s and %(second_user)s boosted your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:36
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others boosted your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:44
+#, python-format
+msgid "%(related_user)s boosted your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:50
+#, python-format
+msgid "%(related_user)s and %(second_user)s boosted your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:59
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others boosted your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:67
+#, python-format
+msgid "%(related_user)s boosted your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:73
+#, python-format
+msgid "%(related_user)s and %(second_user)s boosted your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:82
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others boosted your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:90
+#, python-format
+msgid "%(related_user)s boosted your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:96
+#, python-format
+msgid "%(related_user)s and %(second_user)s boosted your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/boost.html:105
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others boosted your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:21
+#, python-format
+msgid "%(related_user)s liked your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:27
+#, python-format
+msgid "%(related_user)s and %(second_user)s liked your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:36
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others liked your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:44
+#, python-format
+msgid "%(related_user)s liked your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:50
+#, python-format
+msgid "%(related_user)s and %(second_user)s liked your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:59
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others liked your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:67
+#, python-format
+msgid "%(related_user)s liked your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:73
+#, python-format
+msgid "%(related_user)s and %(second_user)s liked your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:82
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others liked your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:90
+#, python-format
+msgid "%(related_user)s liked your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:96
+#, python-format
+msgid "%(related_user)s and %(second_user)s liked your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/fav.html:105
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others liked your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/follow.html:16
+#, python-format
+msgid "%(related_user)s followed you"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/follow.html:20
+#, python-format
+msgid "%(related_user)s and %(second_user)s followed you"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/follow.html:25
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others followed you"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/follow_request.html:15
+#, python-format
+msgid "%(related_user)s sent you a follow request"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/import.html:14
+#, python-format
+msgid "Your import completed."
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/invite.html:16
+#, python-format
+msgid "%(related_user)s invited you to join the group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/invite_request.html:15
+#, python-format
+msgid "New invite request awaiting response"
+msgid_plural "%(display_count)s new invite requests awaiting response"
+msgstr[0] ""
+
+#: bookwyrm/templates/notifications/items/join.html:16
+#, python-format
+msgid "has joined your group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/leave.html:18
+#, python-format
+msgid "%(related_user)s has left your group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/leave.html:26
+#, python-format
+msgid "%(related_user)s and %(second_user)s have left your group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/leave.html:36
+#, python-format
+msgid "%(related_user)s and %(other_user_display_count)s others have left your group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/link_domain.html:15
+#, python-format
+msgid "A new link domain needs review"
+msgid_plural "%(display_count)s new link domains need moderation"
+msgstr[0] "검토해야 할 새로운 link domain이 있습니다."
+
+#: bookwyrm/templates/notifications/items/mention.html:20
+#, python-format
+msgid "%(related_user)s mentioned you in a review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/mention.html:26
+#, python-format
+msgid "%(related_user)s mentioned you in a comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/mention.html:32
+#, python-format
+msgid "%(related_user)s mentioned you in a quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/mention.html:38
+#, python-format
+msgid "%(related_user)s mentioned you in a status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/move_user.html:18
+#, python-format
+msgid "%(related_user)s has moved to %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/move_user.html:25
+#, python-format
+msgid "%(related_user)s has undone their move"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/remove.html:17
+#, python-format
+msgid "has been removed from your group \"%(group_name)s\""
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/remove.html:23
+#, python-format
+msgid "You have been removed from the \"%(group_name)s\" group"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/reply.html:21
+#, python-format
+msgid "%(related_user)s replied to your review of %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/reply.html:27
+#, python-format
+msgid "%(related_user)s replied to your comment on %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/reply.html:33
+#, python-format
+msgid "%(related_user)s replied to your quote from %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/reply.html:39
+#, python-format
+msgid "%(related_user)s replied to your status"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/report.html:15
+#, python-format
+msgid "A new report needs moderation"
+msgid_plural "%(display_count)s new reports need moderation"
+msgstr[0] ""
+
+#: bookwyrm/templates/notifications/items/status_preview.html:4
+#: bookwyrm/templates/snippets/status/content_status.html:62
+msgid "Content warning"
+msgstr "내용 경고"
+
+#: bookwyrm/templates/notifications/items/update.html:16
+#, python-format
+msgid "has changed the privacy level for %(group_name)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/update.html:20
+#, python-format
+msgid "has changed the name of %(group_name)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/update.html:24
+#, python-format
+msgid "has changed the description of %(group_name)s"
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/user_export.html:14
+#, python-format
+msgid "Your user export is ready."
+msgstr ""
+
+#: bookwyrm/templates/notifications/items/user_import.html:14
+#, python-format
+msgid "Your user import is complete."
+msgstr ""
+
+#: bookwyrm/templates/notifications/notifications_page.html:19
+msgid "Delete notifications"
+msgstr ""
+
+#: bookwyrm/templates/notifications/notifications_page.html:31
+msgid "All"
+msgstr "모두"
+
+#: bookwyrm/templates/notifications/notifications_page.html:35
+msgid "Mentions"
+msgstr "멘션"
+
+#: bookwyrm/templates/notifications/notifications_page.html:47
+msgid "You're all caught up!"
+msgstr "모두 따라잡았습니다!"
+
+#: bookwyrm/templates/ostatus/error.html:7
+#, python-format
+msgid "%(account)s is not a valid username"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:8
+#: bookwyrm/templates/ostatus/error.html:13
+msgid "Check you have the correct username before trying again"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:12
+#, python-format
+msgid "%(account)s could not be found or %(remote_domain)s
does not support identity discovery"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:17
+#, python-format
+msgid "%(account)s was found but %(remote_domain)s
does not support 'remote follow'"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:18
+#, python-format
+msgid "Try searching for %(user)s on %(remote_domain)s
instead"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:46
+#, python-format
+msgid "Something went wrong trying to follow %(account)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:47
+msgid "Check you have the correct username before trying again."
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:51
+#, python-format
+msgid "You have blocked %(account)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:55
+#, python-format
+msgid "%(account)s has blocked you"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:59
+#, python-format
+msgid "You are already following %(account)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/error.html:63
+#, python-format
+msgid "You have already requested to follow %(account)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/remote_follow.html:6
+#, python-format
+msgid "Follow %(username)s on the fediverse"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/remote_follow.html:33
+#, python-format
+msgid "Follow %(username)s from another Fediverse account like BookWyrm, Mastodon, or Pleroma."
+msgstr ""
+
+#: bookwyrm/templates/ostatus/remote_follow.html:40
+msgid "User handle to follow from:"
+msgstr "팔로우하려는 이용자의 핸들:"
+
+#: bookwyrm/templates/ostatus/remote_follow.html:42
+msgid "Follow!"
+msgstr "팔로우!"
+
+#: bookwyrm/templates/ostatus/remote_follow_button.html:15
+msgid "Follow on Fediverse"
+msgstr "페디버스에서 팔로우하기"
+
+#: bookwyrm/templates/ostatus/remote_follow_button.html:19
+msgid "This link opens in a pop-up window"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/subscribe.html:8
+#, python-format
+msgid "Log in to %(sitename)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/subscribe.html:10
+#, python-format
+msgid "Error following from %(sitename)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/subscribe.html:12
+#: bookwyrm/templates/ostatus/subscribe.html:22
+#, python-format
+msgid "Follow from %(sitename)s"
+msgstr ""
+
+#: bookwyrm/templates/ostatus/subscribe.html:18
+msgid "Uh oh..."
+msgstr "어랏…"
+
+#: bookwyrm/templates/ostatus/subscribe.html:20
+msgid "Let's log in first..."
+msgstr ""
+
+#: bookwyrm/templates/ostatus/subscribe.html:51
+#, python-format
+msgid "Follow %(username)s"
+msgstr "%(username)s 팔로우"
+
+#: bookwyrm/templates/ostatus/success.html:28
+#, python-format
+msgid "You are now following %(display_name)s!"
+msgstr ""
+
+#: bookwyrm/templates/preferences/2fa.html:4
+#: bookwyrm/templates/preferences/2fa.html:7
+#: bookwyrm/templates/preferences/layout.html:24
+msgid "Two Factor Authentication"
+msgstr "2단계 인증"
+
+#: bookwyrm/templates/preferences/2fa.html:16
+msgid "Successfully updated 2FA settings"
+msgstr "2FA 설정 업데이트를 잘 마쳤습니다."
+
+#: bookwyrm/templates/preferences/2fa.html:24
+msgid "Write down or copy and paste these codes somewhere safe."
+msgstr "이 코드를 적어 두거나 안전한 곳에 복사하여 붙여넣습니다."
+
+#: bookwyrm/templates/preferences/2fa.html:25
+msgid "You must use them in order, and they will not be displayed again."
+msgstr "순서대로 써야 하고, 다시 표시되지 않습니다."
+
+#: bookwyrm/templates/preferences/2fa.html:35
+msgid "Two Factor Authentication is active on your account."
+msgstr "계정에 2단계 인증이 활성 상태입니다."
+
+#: bookwyrm/templates/preferences/2fa.html:36
+#: bookwyrm/templates/preferences/disable-2fa.html:4
+#: bookwyrm/templates/preferences/disable-2fa.html:7
+msgid "Disable 2FA"
+msgstr "2FA 비활성화하기"
+
+#: bookwyrm/templates/preferences/2fa.html:39
+msgid "You can generate backup codes to use in case you do not have access to your authentication app. If you generate new codes, any backup codes previously generated will no longer work."
+msgstr "인증 앱에 액세스할 수 없는 경우에 대비하여 백업 코드를 생성하여 이용할 수 있습니다. 새 코드를 생성하면 이전에 생성한 백업 코드는 더 이상 기능하지 않습니다."
+
+#: bookwyrm/templates/preferences/2fa.html:40
+msgid "Generate backup codes"
+msgstr "백업 코드 생성하기"
+
+#: bookwyrm/templates/preferences/2fa.html:45
+msgid "Scan the QR code with your authentication app and then enter the code from your app below to confirm your app is set up."
+msgstr "인증 앱으로 QR 코드를 스캔한 다음 아래에 앱의 코드를 입력하여 앱이 설정되었는지 확인합니다."
+
+#: bookwyrm/templates/preferences/2fa.html:52
+msgid "Use setup key"
+msgstr "셋업 키 사용하기"
+
+#: bookwyrm/templates/preferences/2fa.html:58
+msgid "Account name:"
+msgstr "계정 이름:"
+
+#: bookwyrm/templates/preferences/2fa.html:65
+msgid "Code:"
+msgstr "코드:"
+
+#: bookwyrm/templates/preferences/2fa.html:73
+msgid "Enter the code from your app:"
+msgstr "2FA앱의 코드 기입:"
+
+#: bookwyrm/templates/preferences/2fa.html:83
+msgid "You can make your account more secure by using Two Factor Authentication (2FA). This will require you to enter a one-time code using a phone app like Authy, Google Authenticator or Microsoft Authenticator each time you log in."
+msgstr "2단계 인증 (2FA)를 이용해 계정을 더욱 안전하게 보호할 수 있습니다. 로그인할 때마다 Authy나Google 인증기, Microsoft 인증기와 같은 휴대전화 앱을 이용해 일회용 코드를 입력해야 합니다."
+
+#: bookwyrm/templates/preferences/2fa.html:85
+msgid "Confirm your password to begin setting up 2FA."
+msgstr "2단계 인증 설정을 시작하려면 암호를 확인해 주시기 바랍니다."
+
+#: bookwyrm/templates/preferences/2fa.html:95
+#: bookwyrm/templates/two_factor_auth/two_factor_prompt.html:37
+msgid "Set up 2FA"
+msgstr "2FA 설정하기"
+
+#: bookwyrm/templates/preferences/alias_user.html:4
+#: bookwyrm/templates/preferences/move_user.html:4
+#: bookwyrm/templates/preferences/move_user.html:7
+#: bookwyrm/templates/preferences/move_user.html:39
+msgid "Move Account"
+msgstr "계정 옮기기"
+
+#: bookwyrm/templates/preferences/alias_user.html:7
+#: bookwyrm/templates/preferences/alias_user.html:34
+msgid "Create Alias"
+msgstr "별칭 만들기"
+
+#: bookwyrm/templates/preferences/alias_user.html:12
+msgid "Add another account as an alias"
+msgstr "다른 계정을 별칭으로 추가하기"
+
+#: bookwyrm/templates/preferences/alias_user.html:16
+msgid "Marking another account as an alias is required if you want to move that account to this one."
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:19
+msgid "This is a reversable action and will not change the functionality of this account."
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:25
+msgid "Enter the username for the account you want to add as an alias e.g. user@example.com :"
+msgstr ""
+
+#: bookwyrm/templates/preferences/alias_user.html:30
+#: bookwyrm/templates/preferences/move_user.html:35
+msgid "Confirm your password:"
+msgstr "암호 확인:"
+
+#: bookwyrm/templates/preferences/alias_user.html:39
+#: bookwyrm/templates/preferences/layout.html:28
+msgid "Aliases"
+msgstr "별칭"
+
+#: bookwyrm/templates/preferences/alias_user.html:49
+msgid "Remove alias"
+msgstr "별칭 제거하기"
+
+#: bookwyrm/templates/preferences/blocks.html:4
+#: bookwyrm/templates/preferences/blocks.html:7
+#: bookwyrm/templates/preferences/layout.html:62
+msgid "Blocked Users"
+msgstr "차단한 이용자"
+
+#: bookwyrm/templates/preferences/blocks.html:12
+msgid "No users currently blocked."
+msgstr "차단한 이용자가 없습니다."
+
+#: bookwyrm/templates/preferences/change_password.html:4
+#: bookwyrm/templates/preferences/change_password.html:7
+#: bookwyrm/templates/preferences/change_password.html:37
+#: bookwyrm/templates/preferences/layout.html:20
+msgid "Change Password"
+msgstr "암호 변경"
+
+#: bookwyrm/templates/preferences/change_password.html:15
+msgid "Successfully changed password"
+msgstr "암호 변경 성공"
+
+#: bookwyrm/templates/preferences/change_password.html:22
+msgid "Current password:"
+msgstr "현재 암호:"
+
+#: bookwyrm/templates/preferences/change_password.html:28
+msgid "New password:"
+msgstr "새 암호:"
+
+#: bookwyrm/templates/preferences/delete_user.html:4
+#: bookwyrm/templates/preferences/delete_user.html:7
+#: bookwyrm/templates/preferences/delete_user.html:40
+#: bookwyrm/templates/preferences/layout.html:36
+#: bookwyrm/templates/settings/users/delete_user_form.html:22
+msgid "Delete Account"
+msgstr "계정 삭제하기"
+
+#: bookwyrm/templates/preferences/delete_user.html:12
+msgid "Deactivate account"
+msgstr "계정 휴면하기"
+
+#: bookwyrm/templates/preferences/delete_user.html:15
+msgid "Your account will be hidden. You can log back in at any time to re-activate your account."
+msgstr "계정을 숨겨둬요. 언제든 다시 돌아와 계정을 휴면 해제할 수 있어요."
+
+#: bookwyrm/templates/preferences/delete_user.html:20
+msgid "Deactivate Account"
+msgstr "계정 휴면"
+
+#: bookwyrm/templates/preferences/delete_user.html:26
+msgid "Permanently delete account"
+msgstr "계정 영구히 지우기"
+
+#: bookwyrm/templates/preferences/delete_user.html:29
+msgid "Deleting your account cannot be undone. The username will not be available to register in the future."
+msgstr "계정을 지우면 되돌릴 수 없어요. 이 이용자 이름은 앞으로 가입 시에 쓸 수 없어요."
+
+#: bookwyrm/templates/preferences/disable-2fa.html:12
+msgid "Disable Two Factor Authentication"
+msgstr "2단계 인증 비활성하기"
+
+#: bookwyrm/templates/preferences/disable-2fa.html:14
+msgid "Disabling 2FA will allow anyone with your username and password to log in to your account."
+msgstr "2FA를 비활성화하면 내 이용자명과 암호만으로 누구나 내 계정에 로그인할 수 있습니다."
+
+#: bookwyrm/templates/preferences/disable-2fa.html:20
+msgid "Turn off 2FA"
+msgstr "2FA 끄기"
+
+#: bookwyrm/templates/preferences/edit_user.html:4
+#: bookwyrm/templates/preferences/edit_user.html:7
+#: bookwyrm/templates/preferences/layout.html:15
+msgid "Edit Profile"
+msgstr "프로필 편집"
+
+#: bookwyrm/templates/preferences/edit_user.html:12
+#: bookwyrm/templates/preferences/edit_user.html:25
+#: bookwyrm/templates/settings/users/user_info.html:8
+#: bookwyrm/templates/user_menu.html:29
+msgid "Profile"
+msgstr "프로필"
+
+#: bookwyrm/templates/preferences/edit_user.html:13
+#: bookwyrm/templates/preferences/edit_user.html:64
+#: bookwyrm/templates/settings/site.html:11
+#: bookwyrm/templates/settings/site.html:89
+#: bookwyrm/templates/setup/config.html:91
+msgid "Display"
+msgstr "표시"
+
+#: bookwyrm/templates/preferences/edit_user.html:14
+#: bookwyrm/templates/preferences/edit_user.html:112
+msgid "Privacy"
+msgstr "개인정보"
+
+#: bookwyrm/templates/preferences/edit_user.html:69
+msgid "Show reading goal prompt in feed"
+msgstr ""
+
+#: bookwyrm/templates/preferences/edit_user.html:75
+msgid "Show suggested users"
+msgstr "추천 이용자 보기"
+
+#: bookwyrm/templates/preferences/edit_user.html:81
+msgid "Show this account in suggested users"
+msgstr "이 계정을 추천 이용자에 보이기"
+
+#: bookwyrm/templates/preferences/edit_user.html:85
+#, python-format
+msgid "Your account will show up in the directory, and may be recommended to other BookWyrm users."
+msgstr ""
+
+#: bookwyrm/templates/preferences/edit_user.html:89
+msgid "Preferred Timezone: "
+msgstr "선호하는 시간대: "
+
+#: bookwyrm/templates/preferences/edit_user.html:101
+msgid "Theme:"
+msgstr "테마:"
+
+#: bookwyrm/templates/preferences/edit_user.html:117
+msgid "Manually approve followers"
+msgstr "수동으로 팔로워 승인"
+
+#: bookwyrm/templates/preferences/edit_user.html:123
+msgid "Hide followers and following on profile"
+msgstr "프로필에서 팔로워 및 팔로잉 숨기기"
+
+#: bookwyrm/templates/preferences/edit_user.html:128
+msgid "Default post privacy:"
+msgstr ""
+
+#: bookwyrm/templates/preferences/edit_user.html:136
+#, python-format
+msgid "Looking for shelf privacy? You can set a separate visibility level for each of your shelves. Go to Your Books, pick a shelf from the tab bar, and click \"Edit shelf.\""
+msgstr "개인정보 보호되는 책꽂이를 찾나요? 각 책꽂이 별로 가시성 수준을 설정할 수 있어요. 내 도서로 이동 후, 탭 바에서 책꽂이를 골라 \"책꽂이 편집\"을 클릭하세요."
+
+#: bookwyrm/templates/preferences/export-user.html:5
+#: bookwyrm/templates/preferences/export-user.html:8
+#: bookwyrm/templates/preferences/layout.html:55
+msgid "Export BookWyrm Account"
+msgstr "BookWyrm 계정 내보내기"
+
+#: bookwyrm/templates/preferences/export-user.html:14
+msgid "You can create an export file here. This will allow you to migrate your data to another BookWyrm account."
+msgstr "이곳에서는 내보낼 파일을 만들 수 있습니다. 그러면 데이터를 다른 BookWyrm 계정으로 이전할 수 있습니다."
+
+#: bookwyrm/templates/preferences/export-user.html:17
+msgid "%(email_sender)s
, may be misconfigured."
+msgstr ""
+
+#: bookwyrm/templates/settings/dashboard/warnings/email_config.html:11
+msgid "Check the EMAIL_SENDER_NAME
and EMAIL_SENDER_DOMAIN
in your .env
file."
+msgstr ""
+
+#: bookwyrm/templates/settings/dashboard/warnings/invites.html:9
+#, python-format
+msgid "%(display_count)s invite request"
+msgid_plural "%(display_count)s invite requests"
+msgstr[0] ""
+
+#: bookwyrm/templates/settings/dashboard/warnings/missing_conduct.html:8
+msgid "Your instance is missing a code of conduct."
+msgstr "귀하의 인스턴스는 행동 지침이 누락됐습니다."
+
+#: bookwyrm/templates/settings/dashboard/warnings/missing_privacy.html:8
+msgid "Your instance is missing a privacy policy."
+msgstr ""
+
+#: bookwyrm/templates/settings/dashboard/warnings/reports.html:9
+#, python-format
+msgid "%(display_count)s open report"
+msgid_plural "%(display_count)s open reports"
+msgstr[0] ""
+
+#: bookwyrm/templates/settings/dashboard/warnings/update_version.html:8
+#, python-format
+msgid "An update is available! You're running v%(current)s and the latest release is %(available)s."
+msgstr ""
+
+#: bookwyrm/templates/settings/email_blocklist/domain_form.html:5
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:10
+msgid "Add domain"
+msgstr "도메인 추가"
+
+#: bookwyrm/templates/settings/email_blocklist/domain_form.html:11
+msgid "Domain:"
+msgstr "도메인:"
+
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:5
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:7
+#: bookwyrm/templates/settings/layout.html:65
+msgid "Email Blocklist"
+msgstr "이메일 차단록"
+
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:18
+msgid "When someone tries to register with an email from this domain, no account will be created. The registration process will appear to have worked."
+msgstr ""
+
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:29
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:27
+msgid "Options"
+msgstr "선택 사항"
+
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:38
+#, python-format
+msgid "%(display_count)s user"
+msgid_plural "%(display_count)s users"
+msgstr[0] ""
+
+#: bookwyrm/templates/settings/email_blocklist/email_blocklist.html:59
+msgid "No email domains currently blocked"
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:6
+#: bookwyrm/templates/settings/email_config.html:8
+#: bookwyrm/templates/settings/layout.html:90
+msgid "Email Configuration"
+msgstr "이메일 구성"
+
+#: bookwyrm/templates/settings/email_config.html:16
+msgid "Error sending test email:"
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:24
+msgid "Successfully sent test email."
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:32
+#: bookwyrm/templates/setup/config.html:102
+msgid "Email sender:"
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:39
+msgid "Email backend:"
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:46
+msgid "Host:"
+msgstr "호스트:"
+
+#: bookwyrm/templates/settings/email_config.html:53
+msgid "Host user:"
+msgstr "호스트 이용자:"
+
+#: bookwyrm/templates/settings/email_config.html:60
+msgid "Port:"
+msgstr "포트:"
+
+#: bookwyrm/templates/settings/email_config.html:67
+msgid "Use TLS:"
+msgstr "TLS 사용:"
+
+#: bookwyrm/templates/settings/email_config.html:74
+msgid "Use SSL:"
+msgstr "SSL 사용:"
+
+#: bookwyrm/templates/settings/email_config.html:83
+#, python-format
+msgid "Send test email to %(email)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/email_config.html:90
+msgid "Send test email"
+msgstr "시험용 이메일 보내기"
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:3
+#: bookwyrm/templates/settings/federation/edit_instance.html:6
+#: bookwyrm/templates/settings/federation/edit_instance.html:15
+#: bookwyrm/templates/settings/federation/edit_instance.html:32
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:3
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:32
+#: bookwyrm/templates/settings/federation/instance_list.html:9
+#: bookwyrm/templates/settings/federation/instance_list.html:10
+msgid "Add instance"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:12
+#: bookwyrm/templates/settings/federation/instance.html:24
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:12
+#: bookwyrm/templates/settings/federation/instance_list.html:3
+#: bookwyrm/templates/settings/federation/instance_list.html:5
+#: bookwyrm/templates/settings/layout.html:47
+msgid "Federated Instances"
+msgstr "연합한 인스턴스"
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:28
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:28
+msgid "Import block list"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:43
+msgid "Instance:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:52
+#: bookwyrm/templates/settings/federation/instance.html:46
+#: bookwyrm/templates/settings/users/user_info.html:113
+msgid "Status:"
+msgstr "상태:"
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:66
+#: bookwyrm/templates/settings/federation/instance.html:40
+#: bookwyrm/templates/settings/users/user_info.html:107
+msgid "Software:"
+msgstr "소프트웨어:"
+
+#: bookwyrm/templates/settings/federation/edit_instance.html:76
+#: bookwyrm/templates/settings/federation/instance.html:43
+#: bookwyrm/templates/settings/users/user_info.html:110
+msgid "Version:"
+msgstr "버전:"
+
+#: bookwyrm/templates/settings/federation/instance.html:17
+msgid "Refresh data"
+msgstr "데이터 새로고침"
+
+#: bookwyrm/templates/settings/federation/instance.html:37
+msgid "Details"
+msgstr "세부 사항"
+
+#: bookwyrm/templates/settings/federation/instance.html:53
+#: bookwyrm/templates/user/layout.html:79
+msgid "Activity"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:56
+msgid "Users:"
+msgstr "이용자:"
+
+#: bookwyrm/templates/settings/federation/instance.html:59
+#: bookwyrm/templates/settings/federation/instance.html:65
+msgid "View all"
+msgstr "모두 보기"
+
+#: bookwyrm/templates/settings/federation/instance.html:62
+#: bookwyrm/templates/settings/users/user_info.html:60
+msgid "Reports:"
+msgstr "제보:"
+
+#: bookwyrm/templates/settings/federation/instance.html:68
+msgid "Followed by us:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:73
+msgid "Followed by them:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:78
+msgid "Blocked by us:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:90
+#: bookwyrm/templates/settings/users/user_info.html:117
+msgid "Notes"
+msgstr "노트"
+
+#: bookwyrm/templates/settings/federation/instance.html:97
+msgid "No notes"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:116
+#: bookwyrm/templates/settings/link_domains/link_domains.html:87
+#: bookwyrm/templates/snippets/block_button.html:5
+msgid "Block"
+msgstr "차단하기"
+
+#: bookwyrm/templates/settings/federation/instance.html:117
+msgid "All users from this instance will be deactivated."
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance.html:122
+#: bookwyrm/templates/snippets/block_button.html:10
+msgid "Un-block"
+msgstr "차단 해제하기"
+
+#: bookwyrm/templates/settings/federation/instance.html:123
+msgid "All users from this instance will be re-activated."
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:6
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:15
+msgid "Import Blocklist"
+msgstr "차단목록 가져오기"
+
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:38
+msgid "Success!"
+msgstr "성공!"
+
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:42
+msgid "Successfully blocked:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:44
+msgid "Failed:"
+msgstr "실패:"
+
+#: bookwyrm/templates/settings/federation/instance_blocklist.html:62
+msgid "Expects a json file in the format provided by FediBlock, with a list of entries that have instance
and url
fields. For example:"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance_list.html:36
+#: bookwyrm/templates/settings/users/server_filter.html:5
+msgid "Instance name"
+msgstr "인스턴스 이름"
+
+#: bookwyrm/templates/settings/federation/instance_list.html:44
+msgid "Last updated"
+msgstr ""
+
+#: bookwyrm/templates/settings/federation/instance_list.html:48
+#: bookwyrm/templates/settings/federation/software_filter.html:5
+msgid "Software"
+msgstr "소프트웨어"
+
+#: bookwyrm/templates/settings/federation/instance_list.html:70
+msgid "No instances found"
+msgstr "인스턴스를 찾을 수 없음"
+
+#: bookwyrm/templates/settings/imports/complete_import_modal.html:4
+#: bookwyrm/templates/settings/imports/complete_user_import_modal.html:4
+msgid "Stop import?"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/complete_user_import_modal.html:7
+msgid "This action will stop the user import before it is complete and cannot be un-done"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:19
+msgid "Disable starting new imports"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:30
+msgid "This is only intended to be used when things have gone very wrong with imports and you need to pause the feature while addressing issues."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:31
+msgid "While imports are disabled, users will not be allowed to start new imports, but existing imports will not be affected."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:32
+msgid "This setting prevents both book imports and user imports."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:37
+msgid "Disable imports"
+msgstr "가져오기 비활성화"
+
+#: bookwyrm/templates/settings/imports/imports.html:51
+msgid "Users are currently unable to start new imports"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:56
+msgid "Enable imports"
+msgstr "가져오기 활성화"
+
+#: bookwyrm/templates/settings/imports/imports.html:64
+msgid "Limit the amount of imports"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:75
+msgid "Some users might try to import a large number of books, which you want to limit."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:76
+#: bookwyrm/templates/settings/imports/imports.html:108
+msgid "Set the value to 0 to not enforce any limit."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:79
+msgid "Set import limit to"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:81
+msgid "books every"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:83
+msgid "days."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:87
+msgid "Set limit"
+msgstr "제한 설정"
+
+#: bookwyrm/templates/settings/imports/imports.html:96
+msgid "Limit how often users can import and export"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:107
+msgid "Some users might try to run user imports or exports very frequently, which you want to limit."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:111
+msgid "Restrict user imports and exports to once every "
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:113
+msgid "hours"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:117
+msgid "Change limit"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:125
+msgid "Book Imports"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:135
+#: bookwyrm/templates/settings/imports/imports.html:225
+msgid "Completed"
+msgstr "완료됨"
+
+#: bookwyrm/templates/settings/imports/imports.html:149
+#: bookwyrm/templates/settings/imports/imports.html:239
+msgid "User"
+msgstr "이용자"
+
+#: bookwyrm/templates/settings/imports/imports.html:158
+#: bookwyrm/templates/settings/imports/imports.html:248
+msgid "Date Updated"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:165
+msgid "Pending items"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:168
+msgid "Successful items"
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:203
+#: bookwyrm/templates/settings/imports/imports.html:295
+msgid "No matching imports found."
+msgstr ""
+
+#: bookwyrm/templates/settings/imports/imports.html:215
+msgid "User Imports"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:4
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:11
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:25
+#: bookwyrm/templates/settings/invites/manage_invites.html:11
+msgid "Invite Requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:15
+#: bookwyrm/templates/settings/invites/manage_invites.html:3
+#: bookwyrm/templates/settings/invites/manage_invites.html:15
+#: bookwyrm/templates/settings/layout.html:42
+#: bookwyrm/templates/user_menu.html:55
+msgid "Invites"
+msgstr "초대"
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:23
+msgid "Ignored Invite Requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:36
+msgid "Date requested"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:40
+msgid "Date accepted"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:45
+msgid "Answer"
+msgstr "답변"
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:51
+msgid "Action"
+msgstr "수행"
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:54
+msgid "No requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:66
+#: bookwyrm/templates/settings/invites/status_filter.html:16
+msgid "Accepted"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:68
+#: bookwyrm/templates/settings/invites/status_filter.html:12
+msgid "Sent"
+msgstr "보냄"
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:70
+#: bookwyrm/templates/settings/invites/status_filter.html:8
+msgid "Requested"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:80
+msgid "Send invite"
+msgstr "초대 보내기"
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:82
+msgid "Re-send invite"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:102
+msgid "Ignore"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:104
+msgid "Un-ignore"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:116
+msgid "Back to pending requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:118
+msgid "View ignored requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:21
+msgid "Generate New Invite"
+msgstr "새 초대장 생성하기"
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:27
+msgid "Expiry:"
+msgstr "만료일:"
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:33
+msgid "Use limit:"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:40
+msgid "Create Invite"
+msgstr "초대장 만들기"
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:48
+msgid "Expires"
+msgstr "만료"
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:49
+msgid "Max uses"
+msgstr "최대 이용"
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:50
+msgid "Times used"
+msgstr ""
+
+#: bookwyrm/templates/settings/invites/manage_invites.html:53
+msgid "No active invites"
+msgstr ""
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_address_form.html:5
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:10
+msgid "Add IP address"
+msgstr ""
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_address_form.html:11
+msgid "Use IP address blocks with caution, and consider using blocks only temporarily, as IP addresses are often shared or change hands. If you block your own IP, you will not be able to access this page."
+msgstr ""
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_address_form.html:18
+msgid "IP Address:"
+msgstr "IP 주소:"
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_address_form.html:24
+msgid "You can block IP ranges using CIDR syntax."
+msgstr ""
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:5
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:7
+#: bookwyrm/templates/settings/layout.html:69
+msgid "IP Address Blocklist"
+msgstr "IP 주소 차단목록"
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:18
+msgid "Any traffic from this IP address will get a 404 response when trying to access any part of the application."
+msgstr ""
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:24
+msgid "Address"
+msgstr "주소"
+
+#: bookwyrm/templates/settings/ip_blocklist/ip_blocklist.html:46
+msgid "No IP addresses currently blocked"
+msgstr "차단한 IP 주소 없음"
+
+#: bookwyrm/templates/settings/layout.html:4
+msgid "Administration"
+msgstr "관리"
+
+#: bookwyrm/templates/settings/layout.html:31
+msgid "Manage Users"
+msgstr "이용자 관리"
+
+#: bookwyrm/templates/settings/layout.html:53
+msgid "Moderation"
+msgstr "중재"
+
+#: bookwyrm/templates/settings/layout.html:57
+#: bookwyrm/templates/settings/reports/reports.html:8
+#: bookwyrm/templates/settings/reports/reports.html:17
+msgid "Reports"
+msgstr "제보"
+
+#: bookwyrm/templates/settings/layout.html:73
+#: bookwyrm/templates/settings/link_domains/link_domains.html:5
+#: bookwyrm/templates/settings/link_domains/link_domains.html:7
+msgid "Link Domains"
+msgstr "링크 도메인"
+
+#: bookwyrm/templates/settings/layout.html:78
+msgid "System"
+msgstr "시스템"
+
+#: bookwyrm/templates/settings/layout.html:86
+msgid "Celery status"
+msgstr ""
+
+#: bookwyrm/templates/settings/layout.html:95
+msgid "Instance Settings"
+msgstr "인스턴스 설정"
+
+#: bookwyrm/templates/settings/layout.html:103
+#: bookwyrm/templates/settings/site.html:4
+#: bookwyrm/templates/settings/site.html:6
+msgid "Site Settings"
+msgstr "사이트 설정"
+
+#: bookwyrm/templates/settings/layout.html:109
+#: bookwyrm/templates/settings/layout.html:112
+#: bookwyrm/templates/settings/registration.html:4
+#: bookwyrm/templates/settings/registration.html:6
+#: bookwyrm/templates/settings/registration_limited.html:4
+#: bookwyrm/templates/settings/registration_limited.html:6
+msgid "Registration"
+msgstr "등록"
+
+#: bookwyrm/templates/settings/layout.html:118
+#: bookwyrm/templates/settings/site.html:107
+#: bookwyrm/templates/settings/themes.html:4
+#: bookwyrm/templates/settings/themes.html:6
+msgid "Themes"
+msgstr "테마"
+
+#: bookwyrm/templates/settings/link_domains/edit_domain_modal.html:5
+#, python-format
+msgid "Set display name for %(url)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:11
+msgid "Link domains must be approved before they are shown on book pages. Please make sure that the domains are not hosting spam, malicious code, or deceptive links before approving."
+msgstr ""
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:45
+msgid "Set display name"
+msgstr "나타낼 이름 설정"
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:53
+msgid "View links"
+msgstr "링크 보기"
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:96
+msgid "No domains currently approved"
+msgstr "승인한 도메인이 없습니다."
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:98
+msgid "No domains currently pending"
+msgstr "계류 중인 도메인은 없습니다."
+
+#: bookwyrm/templates/settings/link_domains/link_domains.html:100
+msgid "No domains currently blocked"
+msgstr "현재 차단한 도메인 없음"
+
+#: bookwyrm/templates/settings/link_domains/link_table.html:43
+msgid "No links available for this domain."
+msgstr ""
+
+#: bookwyrm/templates/settings/registration.html:13
+#: bookwyrm/templates/settings/registration_limited.html:13
+#: bookwyrm/templates/settings/site.html:21
+msgid "Settings saved"
+msgstr "설정 저장함"
+
+#: bookwyrm/templates/settings/registration.html:22
+#: bookwyrm/templates/settings/registration_limited.html:22
+#: bookwyrm/templates/settings/site.html:30
+msgid "Unable to save settings"
+msgstr "설정을 저장할 수 없음"
+
+#: bookwyrm/templates/settings/registration.html:38
+msgid "Allow registration"
+msgstr "이용자 등록 허용"
+
+#: bookwyrm/templates/settings/registration.html:43
+msgid "Default access level:"
+msgstr "기본 접근 레벨:"
+
+#: bookwyrm/templates/settings/registration.html:61
+msgid "Require users to confirm email address"
+msgstr ""
+
+#: bookwyrm/templates/settings/registration.html:63
+msgid "(Recommended if registration is open)"
+msgstr ""
+
+#: bookwyrm/templates/settings/registration.html:68
+msgid "Allow invite requests"
+msgstr "초대 요청 허용"
+
+#: bookwyrm/templates/settings/registration.html:72
+#: bookwyrm/templates/settings/registration_limited.html:42
+msgid "Invite request text:"
+msgstr ""
+
+#: bookwyrm/templates/settings/registration.html:80
+#: bookwyrm/templates/settings/registration_limited.html:50
+msgid "Set a question for invite requests"
+msgstr ""
+
+#: bookwyrm/templates/settings/registration.html:85
+#: bookwyrm/templates/settings/registration_limited.html:55
+msgid "Question:"
+msgstr "물음:"
+
+#: bookwyrm/templates/settings/registration.html:90
+#: bookwyrm/templates/settings/registration_limited.html:67
+msgid "Registration closed text:"
+msgstr "이용자 등록 중단 안내:"
+
+#: bookwyrm/templates/settings/registration_limited.html:29
+msgid "Registration is enabled on this instance"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:13
+msgid "Back to reports"
+msgstr "제보로 돌아가기"
+
+#: bookwyrm/templates/settings/reports/report.html:25
+msgid "Message reporter"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:29
+msgid "Update on your report:"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:37
+msgid "Reported status"
+msgstr "제보된 기록"
+
+#: bookwyrm/templates/settings/reports/report.html:39
+msgid "Status has been deleted"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:48
+msgid "Reported links"
+msgstr "제보된 링크"
+
+#: bookwyrm/templates/settings/reports/report.html:66
+msgid "Moderation Activity"
+msgstr "중재 활동"
+
+#: bookwyrm/templates/settings/reports/report.html:73
+#, python-format
+msgid "%(user)s opened this report"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:86
+#, python-format
+msgid "%(user)s commented on this report:"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report.html:90
+#, python-format
+msgid "%(user)s took an action on this report:"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_header.html:6
+#, python-format
+msgid "Report #%(report_id)s: Status posted by @%(username)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_header.html:13
+#, python-format
+msgid "Report #%(report_id)s: Link added by @%(username)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_header.html:17
+#, python-format
+msgid "Report #%(report_id)s: Link domain"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_header.html:24
+#, python-format
+msgid "Report #%(report_id)s: User @%(username)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_links_table.html:19
+msgid "Approve domain"
+msgstr "허용한 도메인"
+
+#: bookwyrm/templates/settings/reports/report_links_table.html:26
+msgid "Block domain"
+msgstr "차단한 도메인"
+
+#: bookwyrm/templates/settings/reports/report_preview.html:17
+msgid "No notes provided"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_preview.html:24
+#, python-format
+msgid "Reported by @%(username)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/report_preview.html:34
+msgid "Re-open"
+msgstr "다시 열기"
+
+#: bookwyrm/templates/settings/reports/report_preview.html:36
+msgid "Resolve"
+msgstr "해결"
+
+#: bookwyrm/templates/settings/reports/reports.html:6
+#, python-format
+msgid "Reports: %(instance_name)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/reports.html:14
+#, python-format
+msgid "Reports: %(instance_name)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/reports/reports.html:25
+msgid "Open"
+msgstr "열림"
+
+#: bookwyrm/templates/settings/reports/reports.html:28
+msgid "Resolved"
+msgstr "해결"
+
+#: bookwyrm/templates/settings/reports/reports.html:37
+msgid "No reports found."
+msgstr "제보가 없습니다."
+
+#: bookwyrm/templates/settings/site.html:10
+#: bookwyrm/templates/settings/site.html:43
+msgid "Instance Info"
+msgstr "인스턴스 정보"
+
+#: bookwyrm/templates/settings/site.html:12
+#: bookwyrm/templates/settings/site.html:122
+msgid "Footer Content"
+msgstr "푸터 컨텐트"
+
+#: bookwyrm/templates/settings/site.html:46
+msgid "Instance Name:"
+msgstr "인스턴스 이름:"
+
+#: bookwyrm/templates/settings/site.html:50
+msgid "Tagline:"
+msgstr "태그라인:"
+
+#: bookwyrm/templates/settings/site.html:54
+msgid "Instance description:"
+msgstr "인스턴스 설명:"
+
+#: bookwyrm/templates/settings/site.html:58
+msgid "Short description:"
+msgstr "짧은 설명:"
+
+#: bookwyrm/templates/settings/site.html:59
+msgid "Used when the instance is previewed on joinbookwyrm.com. Does not support HTML or Markdown."
+msgstr "서버를 joinbookwyrm.com에서 미리 볼 때 사용됩니다. HTML 또는 마크다운은 지원하지 않습니다."
+
+#: bookwyrm/templates/settings/site.html:63
+msgid "Code of conduct:"
+msgstr "행동 지침:"
+
+#: bookwyrm/templates/settings/site.html:67
+msgid "Privacy Policy:"
+msgstr "개인정보처리방침:"
+
+#: bookwyrm/templates/settings/site.html:72
+msgid "Impressum:"
+msgstr "법률 고지:"
+
+#: bookwyrm/templates/settings/site.html:77
+msgid "Include impressum:"
+msgstr "법률 고지 포함시키기:"
+
+#: bookwyrm/templates/settings/site.html:94
+msgid "Logo:"
+msgstr "로고:"
+
+#: bookwyrm/templates/settings/site.html:98
+msgid "Logo small:"
+msgstr "작은 로고:"
+
+#: bookwyrm/templates/settings/site.html:102
+msgid "Favicon:"
+msgstr "파비콘:"
+
+#: bookwyrm/templates/settings/site.html:110
+msgid "Default theme:"
+msgstr "기본 테마"
+
+#: bookwyrm/templates/settings/site.html:125
+msgid "Support link:"
+msgstr "후원 링크:"
+
+#: bookwyrm/templates/settings/site.html:129
+msgid "Support title:"
+msgstr "후원 제목:"
+
+#: bookwyrm/templates/settings/site.html:133
+msgid "Admin email:"
+msgstr "관리자 이메일:"
+
+#: bookwyrm/templates/settings/site.html:137
+msgid "Additional info:"
+msgstr "부가정보:"
+
+#: bookwyrm/templates/settings/themes.html:10
+msgid "Set instance default theme"
+msgstr "인스턴스 기본 테마 설정"
+
+#: bookwyrm/templates/settings/themes.html:19
+msgid "One of your themes appears to be broken. Selecting this theme will make the application unusable."
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:28
+msgid "Successfully added theme"
+msgstr "테마 추가에 성공함"
+
+#: bookwyrm/templates/settings/themes.html:35
+msgid "How to add a theme"
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:38
+msgid "Copy the theme file into the bookwyrm/static/css/themes
directory on your server from the command line."
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:41
+msgid "Run ./bw-dev compile_themes
and ./bw-dev collectstatic
."
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:44
+msgid "Add the file name using the form below to make it available in the application interface."
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:51
+#: bookwyrm/templates/settings/themes.html:91
+msgid "Add theme"
+msgstr "테마 더하기"
+
+#: bookwyrm/templates/settings/themes.html:57
+msgid "Unable to save theme"
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:72
+#: bookwyrm/templates/settings/themes.html:102
+msgid "Theme name"
+msgstr "테마 이름"
+
+#: bookwyrm/templates/settings/themes.html:82
+msgid "Theme filename"
+msgstr "테마 파일 이름"
+
+#: bookwyrm/templates/settings/themes.html:97
+msgid "Available Themes"
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:105
+msgid "File"
+msgstr "파일"
+
+#: bookwyrm/templates/settings/themes.html:123
+msgid "Remove theme"
+msgstr "테마 제거"
+
+#: bookwyrm/templates/settings/themes.html:134
+msgid "Test theme"
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:143
+msgid "Broken theme"
+msgstr ""
+
+#: bookwyrm/templates/settings/themes.html:152
+msgid "Loaded successfully"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/delete_user_form.html:5
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:52
+msgid "Permanently delete user"
+msgstr "이용자 영구 삭제"
+
+#: bookwyrm/templates/settings/users/delete_user_form.html:12
+#, python-format
+msgid "Are you sure you want to delete %(username)s's account? This action cannot be undone. To proceed, please enter your password to confirm deletion."
+msgstr "%(username)s 계정을 지울까요? 이 동작은 돌이킬 수 없습니다. 계속 진행하려면 암호를 입력하여 지우기를 확인해 주세요."
+
+#: bookwyrm/templates/settings/users/delete_user_form.html:17
+msgid "Your password:"
+msgstr "내 암호:"
+
+#: bookwyrm/templates/settings/users/user_admin.html:9
+#, python-format
+msgid "Users: %(instance_name)s"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_admin.html:29
+msgid "Deleted users"
+msgstr "지운 이용자"
+
+#: bookwyrm/templates/settings/users/user_admin.html:44
+#: bookwyrm/templates/settings/users/username_filter.html:5
+msgid "Username"
+msgstr "이용자명"
+
+#: bookwyrm/templates/settings/users/user_admin.html:48
+msgid "Date Added"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_admin.html:52
+msgid "Last Active"
+msgstr "최근 활동"
+
+#: bookwyrm/templates/settings/users/user_admin.html:61
+msgid "Remote instance"
+msgstr "리모트 인스턴스"
+
+#: bookwyrm/templates/settings/users/user_admin.html:84
+#: bookwyrm/templates/settings/users/user_info.html:127
+msgid "Not set"
+msgstr "설정 안함"
+
+#: bookwyrm/templates/settings/users/user_info.html:20
+msgid "This account is the instance actor for signing HTTP requests."
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_info.html:24
+msgid "View user profile"
+msgstr "이용자 프로필 보기"
+
+#: bookwyrm/templates/settings/users/user_info.html:30
+msgid "Go to user admin"
+msgstr "이용자 관리로 이동"
+
+#: bookwyrm/templates/settings/users/user_info.html:40
+msgid "Local"
+msgstr "로컬"
+
+#: bookwyrm/templates/settings/users/user_info.html:42
+msgid "Remote"
+msgstr "리모트"
+
+#: bookwyrm/templates/settings/users/user_info.html:51
+msgid "User details"
+msgstr "이용자 상세"
+
+#: bookwyrm/templates/settings/users/user_info.html:55
+msgid "Email:"
+msgstr "이메일:"
+
+#: bookwyrm/templates/settings/users/user_info.html:65
+msgid "(View reports)"
+msgstr "(제보 보기)"
+
+#: bookwyrm/templates/settings/users/user_info.html:71
+msgid "Blocked by count:"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_info.html:74
+msgid "Date added:"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_info.html:77
+msgid "Last active date:"
+msgstr "최근 활동일:"
+
+#: bookwyrm/templates/settings/users/user_info.html:80
+msgid "Manually approved followers:"
+msgstr "수동으로 팔로워 승인:"
+
+#: bookwyrm/templates/settings/users/user_info.html:83
+msgid "Discoverable:"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_info.html:87
+msgid "Deactivation reason:"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_info.html:102
+msgid "Instance details"
+msgstr "인스턴스 상세:"
+
+#: bookwyrm/templates/settings/users/user_info.html:124
+msgid "View instance"
+msgstr "인스턴스 보기"
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:6
+msgid "Permanently deleted"
+msgstr "영구 삭제"
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:9
+msgid "User Actions"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:15
+msgid "This is the instance admin actor"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:18
+msgid "You must not delete or disable this account as it is critical to the functioning of your server. This actor signs outgoing GET requests to smooth interaction with secure ActivityPub servers."
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:19
+msgid "This account is not discoverable by ordinary users and does not have a profile page."
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:35
+msgid "Activate user"
+msgstr "활성 이용자"
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:41
+msgid "Suspend user"
+msgstr "정지 이용자"
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:46
+msgid "Un-suspend user"
+msgstr ""
+
+#: bookwyrm/templates/settings/users/user_moderation_actions.html:68
+msgid "Access level:"
+msgstr "접근 레벨:"
+
+#: bookwyrm/templates/setup/admin.html:5
+msgid "Set up BookWyrm"
+msgstr ""
+
+#: bookwyrm/templates/setup/admin.html:7
+msgid "Your account as a user and an admin"
+msgstr ""
+
+#: bookwyrm/templates/setup/admin.html:13
+msgid "Create your account"
+msgstr "내 계정 만들기"
+
+#: bookwyrm/templates/setup/admin.html:20
+msgid "Admin key:"
+msgstr "관리 키:"
+
+#: bookwyrm/templates/setup/admin.html:32
+msgid "An admin key was created when you installed BookWyrm. You can get your admin key by running ./bw-dev admin_code
from the command line on your server."
+msgstr ""
+
+#: bookwyrm/templates/setup/admin.html:45
+msgid "As an admin, you'll be able to configure the instance name and information, and moderate your instance. This means you will have access to private information about your users, and are responsible for responding to reports of bad behavior or spam."
+msgstr ""
+
+#: bookwyrm/templates/setup/admin.html:51
+msgid "Once the instance is set up, you can promote other users to moderator or admin roles from the admin panel."
+msgstr ""
+
+#: bookwyrm/templates/setup/admin.html:55
+msgid "Learn more about moderation"
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:5
+msgid "Instance Configuration"
+msgstr "인스턴스 구성"
+
+#: bookwyrm/templates/setup/config.html:7
+msgid "Make sure everything looks right before proceeding"
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:18
+msgid "You are running BookWyrm in debug mode. This should never be used in a production environment."
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:30
+msgid "Your domain appears to be misconfigured. It should not include protocol or slashes."
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:42
+msgid "You are running BookWyrm in production mode without https. USE_HTTPS should be enabled in production."
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:52 bookwyrm/templates/user_menu.html:44
+msgid "Settings"
+msgstr "설정"
+
+#: bookwyrm/templates/setup/config.html:56
+msgid "Instance domain:"
+msgstr "인스턴스 도메인:"
+
+#: bookwyrm/templates/setup/config.html:63
+msgid "Protocol:"
+msgstr "프로토콜:"
+
+#: bookwyrm/templates/setup/config.html:81
+msgid "Using S3:"
+msgstr "S3 사용:"
+
+#: bookwyrm/templates/setup/config.html:95
+msgid "Default interface language:"
+msgstr "기본 인터페이스 언어:"
+
+#: bookwyrm/templates/setup/config.html:109
+msgid "Enable preview images:"
+msgstr "미리보기 이미지 활성화:"
+
+#: bookwyrm/templates/setup/config.html:116
+msgid "Enable image thumbnails:"
+msgstr "이미지 섬네일 활성화:"
+
+#: bookwyrm/templates/setup/config.html:128
+msgid "Does everything look right?"
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:130
+msgid "This is your last chance to set your domain and protocol."
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:144
+msgid "You can change your instance settings in the .env
file on your server."
+msgstr ""
+
+#: bookwyrm/templates/setup/config.html:148
+msgid "View installation instructions"
+msgstr "설치 과정 설명 보기"
+
+#: bookwyrm/templates/setup/layout.html:5
+msgid "Instance Setup"
+msgstr "인스턴스 설정"
+
+#: bookwyrm/templates/setup/layout.html:21
+msgid "Installing BookWyrm"
+msgstr "BookWyrm 설치 중"
+
+#: bookwyrm/templates/setup/layout.html:24
+msgid "Need help?"
+msgstr ""
+
+#: bookwyrm/templates/shelf/create_shelf_form.html:5
+#: bookwyrm/templates/shelf/shelf.html:74
+msgid "Create shelf"
+msgstr "책꽃이 만들기"
+
+#: bookwyrm/templates/shelf/edit_shelf_form.html:5
+msgid "Edit Shelf"
+msgstr "책꽂이 편집"
+
+#: bookwyrm/templates/shelf/shelf.html:41
+#: bookwyrm/templatetags/shelf_tags.py:13 bookwyrm/views/shelf/shelf.py:53
+msgid "All books"
+msgstr "모든 도서"
+
+#: bookwyrm/templates/shelf/shelf.html:66
+msgid "Import Books"
+msgstr "도서 가져오기"
+
+#: bookwyrm/templates/shelf/shelf.html:99
+#, python-format
+msgid "%(formatted_count)s book"
+msgid_plural "%(formatted_count)s books"
+msgstr[0] ""
+
+#: bookwyrm/templates/shelf/shelf.html:106
+#, python-format
+msgid "(showing %(start)s-%(end)s)"
+msgstr "(%(start)s-%(end)s 보임)"
+
+#: bookwyrm/templates/shelf/shelf.html:118
+msgid "Edit shelf"
+msgstr "책꽂이 편집"
+
+#: bookwyrm/templates/shelf/shelf.html:126
+msgid "Delete shelf"
+msgstr "책꽂이 지우기"
+
+#: bookwyrm/templates/shelf/shelf.html:154
+#: bookwyrm/templates/shelf/shelf.html:180
+msgid "Shelved"
+msgstr "책 가져온 날"
+
+#: bookwyrm/templates/shelf/shelf.html:155
+#: bookwyrm/templates/shelf/shelf.html:183
+msgid "Started"
+msgstr "시작한 날"
+
+#: bookwyrm/templates/shelf/shelf.html:156
+#: bookwyrm/templates/shelf/shelf.html:186
+msgid "Finished"
+msgstr "마침"
+
+#: bookwyrm/templates/shelf/shelf.html:156
+#: bookwyrm/templates/shelf/shelf.html:186
+msgid "Until"
+msgstr "끝낸 날"
+
+#: bookwyrm/templates/shelf/shelf.html:212
+msgid "This shelf is empty."
+msgstr "이 책꽂이는 비었어요."
+
+#: bookwyrm/templates/snippets/add_to_group_button.html:16
+msgid "Invite"
+msgstr ""
+
+#: bookwyrm/templates/snippets/add_to_group_button.html:25
+msgid "Uninvite"
+msgstr ""
+
+#: bookwyrm/templates/snippets/add_to_group_button.html:29
+#, python-format
+msgid "Remove @%(username)s"
+msgstr "@%(username)s 제거"
+
+#: bookwyrm/templates/snippets/announcement.html:28
+#, python-format
+msgid "Posted by %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/authors.html:22
+#: bookwyrm/templates/snippets/trimmed_list.html:14
+#, python-format
+msgid "and %(remainder_count_display)s other"
+msgid_plural "and %(remainder_count_display)s others"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/book_cover.html:63
+msgid "No cover"
+msgstr "표지 없음"
+
+#: bookwyrm/templates/snippets/book_titleby.html:11
+#, python-format
+msgid "%(title)s by"
+msgstr ""
+
+#: bookwyrm/templates/snippets/boost_button.html:20
+#: bookwyrm/templates/snippets/boost_button.html:21
+msgid "Boost"
+msgstr "부스트"
+
+#: bookwyrm/templates/snippets/boost_button.html:33
+#: bookwyrm/templates/snippets/boost_button.html:34
+msgid "Un-boost"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status.html:36
+msgid "Quote"
+msgstr "인용"
+
+#: bookwyrm/templates/snippets/create_status/comment.html:15
+msgid "Some thoughts on the book"
+msgstr "책에 대한 몇몇 생각"
+
+#: bookwyrm/templates/snippets/create_status/comment.html:27
+#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:18
+msgid "Progress:"
+msgstr "진도:"
+
+#: bookwyrm/templates/snippets/create_status/comment.html:53
+#: bookwyrm/templates/snippets/progress_field.html:18
+msgid "pages"
+msgstr "쪽"
+
+#: bookwyrm/templates/snippets/create_status/comment.html:59
+#: bookwyrm/templates/snippets/progress_field.html:23
+msgid "percent"
+msgstr "퍼센트"
+
+#: bookwyrm/templates/snippets/create_status/comment.html:66
+#, python-format
+msgid "of %(pages)s pages"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/content_field.html:18
+#: bookwyrm/templates/snippets/status/layout.html:34
+#: bookwyrm/templates/snippets/status/layout.html:53
+#: bookwyrm/templates/snippets/status/layout.html:54
+msgid "Reply"
+msgstr "답하기"
+
+#: bookwyrm/templates/snippets/create_status/content_field.html:18
+msgid "Content"
+msgstr "컨텐트"
+
+#: bookwyrm/templates/snippets/create_status/content_warning_field.html:9
+msgid "Include spoiler alert"
+msgstr "스포일러 경고 포함"
+
+#: bookwyrm/templates/snippets/create_status/content_warning_field.html:18
+msgid "Spoilers/content warnings:"
+msgstr "스포일러/내용경고:"
+
+#: bookwyrm/templates/snippets/create_status/content_warning_field.html:27
+msgid "Spoilers ahead!"
+msgstr "스포일러 있음!"
+
+#: bookwyrm/templates/snippets/create_status/layout.html:45
+#: bookwyrm/templates/snippets/reading_modals/form.html:7
+msgid "Comment:"
+msgstr "코멘트:"
+
+#: bookwyrm/templates/snippets/create_status/post_options_block.html:19
+msgid "Update"
+msgstr "업데이트"
+
+#: bookwyrm/templates/snippets/create_status/post_options_block.html:21
+msgid "Post"
+msgstr "게시"
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:16
+msgid "Quote:"
+msgstr "인용:"
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:24
+#, python-format
+msgid "An excerpt from '%(book_title)s'"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:31
+msgid "Position:"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:44
+msgid "On page:"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:50
+msgid "At percent:"
+msgstr "퍼센트:"
+
+#: bookwyrm/templates/snippets/create_status/quotation.html:69
+msgid "to"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/review.html:24
+#, python-format
+msgid "Your review of '%(book_title)s'"
+msgstr ""
+
+#: bookwyrm/templates/snippets/create_status/review.html:39
+msgid "Review:"
+msgstr "서평:"
+
+#: bookwyrm/templates/snippets/fav_button.html:16
+#: bookwyrm/templates/snippets/fav_button.html:17
+msgid "Like"
+msgstr "좋아요"
+
+#: bookwyrm/templates/snippets/fav_button.html:30
+#: bookwyrm/templates/snippets/fav_button.html:31
+msgid "Un-like"
+msgstr "좋아요 해제"
+
+#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:5
+msgid "Filters"
+msgstr "필터"
+
+#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:10
+#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:17
+msgid "Filters are applied"
+msgstr "필터 적용함"
+
+#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:20
+msgid "Clear filters"
+msgstr "필터 해제하기"
+
+#: bookwyrm/templates/snippets/filters_panel/filters_panel.html:43
+msgid "Apply filters"
+msgstr "필터 적용"
+
+#: bookwyrm/templates/snippets/follow_button.html:20
+#, python-format
+msgid "Follow @%(username)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/follow_button.html:22
+msgid "Follow"
+msgstr "팔로우"
+
+#: bookwyrm/templates/snippets/follow_button.html:31
+msgid "Undo follow request"
+msgstr "팔로우 요청을 취소"
+
+#: bookwyrm/templates/snippets/follow_button.html:36
+#, python-format
+msgid "Unfollow @%(username)s"
+msgstr "@%(username)s 언팔로우"
+
+#: bookwyrm/templates/snippets/follow_button.html:38
+msgid "Unfollow"
+msgstr "언팔로우"
+
+#: bookwyrm/templates/snippets/follow_request_buttons.html:7
+#: bookwyrm/templates/snippets/join_invitation_buttons.html:9
+msgid "Accept"
+msgstr "수락"
+
+#: bookwyrm/templates/snippets/footer.html:16
+msgid "Documentation"
+msgstr "문서"
+
+#: bookwyrm/templates/snippets/footer.html:42
+#, python-format
+msgid "Support %(site_name)s on %(support_title)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/footer.html:49
+msgid "BookWyrm's source code is freely available. You can contribute or report issues on GitHub."
+msgstr "BookWyrm의 소스 코드는 자유롭게 사용할 수 있습니다. GitHub에서 기여하거나 이슈를 제보할 수 있습니다."
+
+#: bookwyrm/templates/snippets/form_rate_stars.html:20
+#: bookwyrm/templates/snippets/stars.html:23
+msgid "No rating"
+msgstr "별점 없음"
+
+#: bookwyrm/templates/snippets/form_rate_stars.html:28
+#, python-format
+msgid "%(half_rating)s star"
+msgid_plural "%(half_rating)s stars"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/form_rate_stars.html:64
+#: bookwyrm/templates/snippets/stars.html:7
+#, python-format
+msgid "%(rating)s star"
+msgid_plural "%(rating)s stars"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/generated_status/goal.html:2
+#, python-format
+msgid "set a goal to read %(counter)s book in %(year)s"
+msgid_plural "set a goal to read %(counter)s books in %(year)s"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/generated_status/rating.html:3
+#, python-format
+msgid "rated %(title)s: %(display_rating)s star"
+msgid_plural "rated %(title)s: %(display_rating)s stars"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/generated_status/review_pure_name.html:4
+#, python-format
+msgid "Review of \"%(book_title)s\" (%(display_rating)s star): %(review_title)s"
+msgid_plural "Review of \"%(book_title)s\" (%(display_rating)s stars): %(review_title)s"
+msgstr[0] ""
+
+#: bookwyrm/templates/snippets/generated_status/review_pure_name.html:12
+#, python-format
+msgid "Review of \"%(book_title)s\": %(review_title)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/goal_form.html:4
+#, python-format
+msgid "Set a goal for how many books you'll finish reading in %(year)s, and track your progress throughout the year."
+msgstr "%(year)s년에 몇 권의 책을 끝까지 읽을 것인지 목표를 설정하고 한 해 동안의 성과를 추적합시다."
+
+#: bookwyrm/templates/snippets/goal_form.html:16
+msgid "Reading goal:"
+msgstr "읽기 목표:"
+
+#: bookwyrm/templates/snippets/goal_form.html:21
+msgid "books"
+msgstr "책"
+
+#: bookwyrm/templates/snippets/goal_form.html:26
+msgid "Goal privacy:"
+msgstr "목표의 프라이버시:"
+
+#: bookwyrm/templates/snippets/goal_form.html:33
+#: bookwyrm/templates/snippets/reading_modals/layout.html:13
+msgid "Post to feed"
+msgstr "피드에 게시"
+
+#: bookwyrm/templates/snippets/goal_form.html:37
+msgid "Set goal"
+msgstr "목표 설정"
+
+#: bookwyrm/templates/snippets/goal_progress.html:7
+msgctxt "Goal successfully completed"
+msgid "Success!"
+msgstr "성공!"
+
+#: bookwyrm/templates/snippets/goal_progress.html:9
+#, python-format
+msgid "%(percent)s%% complete!"
+msgstr ""
+
+#: bookwyrm/templates/snippets/goal_progress.html:12
+#, python-format
+msgid "You've read %(read_count)s of %(goal_count)s books."
+msgstr ""
+
+#: bookwyrm/templates/snippets/goal_progress.html:14
+#, python-format
+msgid "%(username)s has read %(read_count)s of %(goal_count)s books."
+msgstr ""
+
+#: bookwyrm/templates/snippets/move_user_buttons.html:10
+msgid "Follow at new account"
+msgstr "새 계정에서 팔로우하기"
+
+#: bookwyrm/templates/snippets/moved_user_notice.html:7
+#, python-format
+msgid "%(user)s has moved to %(moved_to_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/page_text.html:8
+#, python-format
+msgid "page %(page)s of %(total_pages)s"
+msgstr "%(total_pages)s쪽 중 %(page)s쪽"
+
+#: bookwyrm/templates/snippets/page_text.html:14
+#, python-format
+msgid "page %(page)s"
+msgstr "%(page)s쪽"
+
+#: bookwyrm/templates/snippets/pagination.html:13
+msgid "Newer"
+msgstr ""
+
+#: bookwyrm/templates/snippets/pagination.html:15
+msgid "Previous"
+msgstr ""
+
+#: bookwyrm/templates/snippets/pagination.html:28
+msgid "Older"
+msgstr ""
+
+#: bookwyrm/templates/snippets/privacy-icons.html:12
+msgid "Followers-only"
+msgstr "팔로워만"
+
+#: bookwyrm/templates/snippets/rate_action.html:5
+msgid "Leave a rating"
+msgstr "별점 남기기"
+
+#: bookwyrm/templates/snippets/rate_action.html:20
+msgid "Rate"
+msgstr "별점"
+
+#: bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html:6
+#, python-format
+msgid "Finish \"%(book_title)s\""
+msgstr ""
+
+#: bookwyrm/templates/snippets/reading_modals/form.html:9
+msgid "(Optional)"
+msgstr ""
+
+#: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:6
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:61
+msgid "Update progress"
+msgstr ""
+
+#: bookwyrm/templates/snippets/reading_modals/start_reading_modal.html:6
+#, python-format
+msgid "Start \"%(book_title)s\""
+msgstr ""
+
+#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:6
+#, python-format
+msgid "Stop Reading \"%(book_title)s\""
+msgstr ""
+
+#: bookwyrm/templates/snippets/reading_modals/stop_reading_modal.html:32
+#: bookwyrm/templates/snippets/shelf_selector.html:53
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:21
+msgid "Stopped reading"
+msgstr "읽다 멈춘 것"
+
+#: bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html:6
+#, python-format
+msgid "Want to Read \"%(book_title)s\""
+msgstr ""
+
+#: bookwyrm/templates/snippets/register_form.html:18
+msgid "Choose wisely! Your username cannot be changed."
+msgstr "신중히 고르세요! 이용자명은 바꿀 수 없어요."
+
+#: bookwyrm/templates/snippets/register_form.html:66
+msgid "Sign Up"
+msgstr "가입하기"
+
+#: bookwyrm/templates/snippets/report_modal.html:8
+#, python-format
+msgid "Report @%(username)s's status"
+msgstr "@%(username)s의 게시물을 제보"
+
+#: bookwyrm/templates/snippets/report_modal.html:10
+#, python-format
+msgid "Report %(domain)s link"
+msgstr ""
+
+#: bookwyrm/templates/snippets/report_modal.html:12
+#, python-format
+msgid "Report @%(username)s"
+msgstr "@%(username)s를 제보"
+
+#: bookwyrm/templates/snippets/report_modal.html:34
+#, python-format
+msgid "This report will be sent to %(site_name)s's moderators for review."
+msgstr ""
+
+#: bookwyrm/templates/snippets/report_modal.html:36
+msgid "Links from this domain will be removed until your report has been reviewed."
+msgstr ""
+
+#: bookwyrm/templates/snippets/report_modal.html:41
+msgid "More info about this report:"
+msgstr ""
+
+#: bookwyrm/templates/snippets/shelf_selector.html:7
+msgid "Move book"
+msgstr "책 정리"
+
+#: bookwyrm/templates/snippets/shelf_selector.html:38
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:17
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:33
+msgid "Start reading"
+msgstr "읽기 시작"
+
+#: bookwyrm/templates/snippets/shelf_selector.html:60
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:38
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:55
+msgid "Want to read"
+msgstr ""
+
+#: bookwyrm/templates/snippets/shelf_selector.html:81
+#: bookwyrm/templates/snippets/shelf_selector.html:95
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:73
+#, python-format
+msgid "Remove from %(name)s"
+msgstr "%(name)s에서 제거"
+
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown.html:5
+msgid "More shelves"
+msgstr "더 많은 책꽂이"
+
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:31
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:48
+msgid "Stop reading"
+msgstr "읽기 멈춤"
+
+#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:40
+msgid "Finish reading"
+msgstr "읽기 마치기"
+
+#: bookwyrm/templates/snippets/status/content_status.html:69
+msgid "Show status"
+msgstr "기록 보기"
+
+#: bookwyrm/templates/snippets/status/content_status.html:91
+#, python-format
+msgid "(Page %(page)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/content_status.html:91
+#, python-format
+msgid "%(endpage)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/content_status.html:93
+#, python-format
+msgid "(%(percent)s%%"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/content_status.html:93
+#, python-format
+msgid " - %(endpercent)s%%"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/content_status.html:116
+msgid "Open image in new window"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/content_status.html:137
+msgid "Hide status"
+msgstr "숨기기"
+
+#: bookwyrm/templates/snippets/status/header.html:45
+#, python-format
+msgid "edited %(date)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/comment.html:8
+#, python-format
+msgid "commented on %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/comment.html:15
+#, python-format
+msgid "commented on %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/note.html:8
+#, python-format
+msgid "replied to %(username)s's status"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/quotation.html:8
+#, python-format
+msgid "quoted %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/quotation.html:15
+#, python-format
+msgid "quoted %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/rating.html:3
+#, python-format
+msgid "rated %(book)s:"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/read.html:10
+#, python-format
+msgid "finished reading %(book)s by %(author_name)s"
+msgstr "님이 %(author_name)s의 %(book)s 읽기 마침"
+
+#: bookwyrm/templates/snippets/status/headers/read.html:17
+#, python-format
+msgid "finished reading %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/reading.html:10
+#, python-format
+msgid "started reading %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/reading.html:17
+#, python-format
+msgid "started reading %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/review.html:8
+#, python-format
+msgid "reviewed %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/review.html:15
+#, python-format
+msgid "reviewed %(book)s"
+msgstr "님이 서평한 %(book)s"
+
+#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:10
+#, python-format
+msgid "stopped reading %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/stopped_reading.html:17
+#, python-format
+msgid "stopped reading %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/to_read.html:10
+#, python-format
+msgid "wants to read %(book)s by %(author_name)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/headers/to_read.html:17
+#, python-format
+msgid "wants to read %(book)s"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/layout.html:24
+#: bookwyrm/templates/snippets/status/status_options.html:17
+msgid "Delete status"
+msgstr "기록 지우기"
+
+#: bookwyrm/templates/snippets/status/layout.html:57
+#: bookwyrm/templates/snippets/status/layout.html:58
+msgid "Boost status"
+msgstr "기록 부스트"
+
+#: bookwyrm/templates/snippets/status/layout.html:61
+#: bookwyrm/templates/snippets/status/layout.html:62
+msgid "Like status"
+msgstr ""
+
+#: bookwyrm/templates/snippets/status/status.html:10
+msgid "boosted"
+msgstr "부스트함"
+
+#: bookwyrm/templates/snippets/status/status_options.html:7
+#: bookwyrm/templates/snippets/user_options.html:7
+msgid "More options"
+msgstr ""
+
+#: bookwyrm/templates/snippets/switch_edition_button.html:5
+msgid "Switch to this edition"
+msgstr "이 판으로 바꾸기"
+
+#: bookwyrm/templates/snippets/table-sort-header.html:6
+msgid "Sorted ascending"
+msgstr ""
+
+#: bookwyrm/templates/snippets/table-sort-header.html:10
+msgid "Sorted descending"
+msgstr ""
+
+#: bookwyrm/templates/snippets/trimmed_text.html:17
+msgid "Show more"
+msgstr "더 보기"
+
+#: bookwyrm/templates/snippets/trimmed_text.html:35
+msgid "Show less"
+msgstr "덜 보기"
+
+#: bookwyrm/templates/snippets/user_active_tag.html:5
+msgid "Moved"
+msgstr ""
+
+#: bookwyrm/templates/snippets/user_active_tag.html:12
+msgid "Deleted"
+msgstr "지움"
+
+#: bookwyrm/templates/snippets/user_active_tag.html:15
+msgid "Inactive"
+msgstr "비활성화"
+
+#: bookwyrm/templates/two_factor_auth/two_factor_login.html:29
+msgid "2FA check"
+msgstr "2FA 체크"
+
+#: bookwyrm/templates/two_factor_auth/two_factor_login.html:37
+msgid "Enter the code from your authenticator app:"
+msgstr ""
+
+#: bookwyrm/templates/two_factor_auth/two_factor_login.html:41
+msgid "Confirm and Log In"
+msgstr ""
+
+#: bookwyrm/templates/two_factor_auth/two_factor_prompt.html:29
+msgid "2FA is available"
+msgstr "2FA 쓸 수 있음"
+
+#: bookwyrm/templates/two_factor_auth/two_factor_prompt.html:34
+msgid "You can secure your account by setting up two factor authentication in your user preferences. This will require a one-time code from your phone in addition to your password each time you log in."
+msgstr ""
+
+#: bookwyrm/templates/user/books_header.html:9
+#, python-format
+msgid "%(username)s's books"
+msgstr ""
+
+#: bookwyrm/templates/user/goal.html:12
+#, python-format
+msgid "%(year)s Reading Progress"
+msgstr ""
+
+#: bookwyrm/templates/user/goal.html:16
+msgid "Edit Goal"
+msgstr "목표 수정"
+
+#: bookwyrm/templates/user/goal.html:32
+#, python-format
+msgid "%(name)s hasn't set a reading goal for %(year)s."
+msgstr ""
+
+#: bookwyrm/templates/user/goal.html:44
+#, python-format
+msgid "Your %(year)s Books"
+msgstr ""
+
+#: bookwyrm/templates/user/goal.html:46
+#, python-format
+msgid "%(username)s's %(year)s Books"
+msgstr ""
+
+#: bookwyrm/templates/user/groups.html:14
+msgid "Your Groups"
+msgstr "내 그룹"
+
+#: bookwyrm/templates/user/groups.html:16
+#, python-format
+msgid "Groups: %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/user/layout.html:59
+msgid "Follow Requests"
+msgstr ""
+
+#: bookwyrm/templates/user/layout.html:83
+#: bookwyrm/templates/user/reviews_comments.html:6
+#: bookwyrm/templates/user/reviews_comments.html:12
+msgid "Reviews and Comments"
+msgstr "서평과 코멘트"
+
+#: bookwyrm/templates/user/lists.html:16
+#, python-format
+msgid "Lists: %(username)s"
+msgstr ""
+
+#: bookwyrm/templates/user/lists.html:22 bookwyrm/templates/user/lists.html:34
+msgid "Create list"
+msgstr "목록 만들기"
+
+#: bookwyrm/templates/user/moved.html:25
+#: bookwyrm/templates/user/user_preview.html:22
+#, python-format
+msgid "Joined %(date)s"
+msgstr "참여: %(date)s"
+
+#: bookwyrm/templates/user/relationships/followers.html:36
+#, python-format
+msgid "%(username)s has no followers"
+msgstr ""
+
+#: bookwyrm/templates/user/relationships/following.html:6
+#: bookwyrm/templates/user/relationships/following.html:11
+#: bookwyrm/templates/user/relationships/following.html:21
+#: bookwyrm/templates/user/relationships/layout.html:15
+msgid "Following"
+msgstr "팔로잉"
+
+#: bookwyrm/templates/user/relationships/following.html:30
+#, python-format
+msgid "%(username)s isn't following any users"
+msgstr ""
+
+#: bookwyrm/templates/user/reviews_comments.html:26
+msgid "No reviews or comments yet!"
+msgstr "아직 서평 혹은 코멘트가 없어요!"
+
+#: bookwyrm/templates/user/user.html:20
+msgid "Edit profile"
+msgstr "프로필 수정"
+
+#: bookwyrm/templates/user/user.html:42
+#, python-format
+msgid "View all %(size)s"
+msgstr "%(size)s권 모두 보기"
+
+#: bookwyrm/templates/user/user.html:61
+msgid "View all books"
+msgstr "모든 도서 보기"
+
+#: bookwyrm/templates/user/user.html:69
+#, python-format
+msgid "%(current_year)s Reading Goal"
+msgstr ""
+
+#: bookwyrm/templates/user/user.html:76
+msgid "User Activity"
+msgstr "이용자 활동"
+
+#: bookwyrm/templates/user/user.html:82
+msgid "Show RSS Options"
+msgstr "RSS 옵션 보여주기"
+
+#: bookwyrm/templates/user/user.html:88
+msgid "RSS feed"
+msgstr "RSS 피드"
+
+#: bookwyrm/templates/user/user.html:104
+msgid "Complete feed"
+msgstr ""
+
+#: bookwyrm/templates/user/user.html:109
+msgid "Reviews only"
+msgstr "서평만"
+
+#: bookwyrm/templates/user/user.html:114
+msgid "Quotes only"
+msgstr "인용만"
+
+#: bookwyrm/templates/user/user.html:119
+msgid "Comments only"
+msgstr "코멘트만"
+
+#: bookwyrm/templates/user/user.html:135
+msgid "No activities yet!"
+msgstr ""
+
+#: bookwyrm/templates/user/user_preview.html:26
+#, python-format
+msgid "%(display_count)s follower"
+msgid_plural "%(display_count)s followers"
+msgstr[0] ""
+
+#: bookwyrm/templates/user/user_preview.html:31
+#, python-format
+msgid "%(counter)s following"
+msgstr ""
+
+#: bookwyrm/templates/user/user_preview.html:45
+#, python-format
+msgid "%(mutuals_display)s follower you follow"
+msgid_plural "%(mutuals_display)s followers you follow"
+msgstr[0] ""
+
+#: bookwyrm/templates/user/user_preview.html:49
+msgid "No followers you follow"
+msgstr "팔로워 없음"
+
+#: bookwyrm/templates/user_menu.html:7
+msgid "View profile and more"
+msgstr ""
+
+#: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28
+msgid "File exceeds maximum size: 10MB"
+msgstr ""
+
+#: bookwyrm/templatetags/list_page_tags.py:14
+#, python-format
+msgid "Book List: %(name)s"
+msgstr ""
+
+#: bookwyrm/templatetags/list_page_tags.py:22
+#, python-format
+msgid "%(num)d book - by %(user)s"
+msgid_plural "%(num)d books - by %(user)s"
+msgstr[0] ""
+
+#: bookwyrm/templatetags/utilities.py:49
+#, python-format
+msgid "%(title)s: %(subtitle)s"
+msgstr ""
+
+#: bookwyrm/views/rss_feed.py:35
+#, python-brace-format
+msgid "Status updates from {obj.display_name}"
+msgstr ""
+
+#: bookwyrm/views/rss_feed.py:80
+#, python-brace-format
+msgid "Reviews from {obj.display_name}"
+msgstr ""
+
+#: bookwyrm/views/rss_feed.py:122
+#, python-brace-format
+msgid "Quotes from {obj.display_name}"
+msgstr ""
+
+#: bookwyrm/views/rss_feed.py:164
+#, python-brace-format
+msgid "Comments from {obj.display_name}"
+msgstr ""
+
+#: bookwyrm/views/updates.py:45
+#, python-format
+msgid "Load %(count)d unread status"
+msgid_plural "Load %(count)d unread statuses"
+msgstr[0] ""
+
diff --git a/nginx/development b/nginx/development
index 841db0124..2c3a1d02f 100644
--- a/nginx/development
+++ b/nginx/development
@@ -61,16 +61,29 @@ server {
proxy_pass http://web;
}
- # directly serve images and static files from the
+ # directly serve static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
- location ~ ^/(images|static)/ {
+ location ~ ^/static/ {
root /app;
try_files $uri =404;
add_header X-Cache-Status STATIC;
access_log off;
}
+ # same with image files not in static folder
+ location ~ \.(bmp|ico|jpg|jpeg|png|svg|tif|tiff|webp)$ {
+ root /app;
+ try_files $uri =404;
+ add_header X-Cache-Status STATIC;
+ access_log off;
+ }
+
+ # block access to any non-image files from images
+ location ~ ^/images/ {
+ return 403;
+ }
+
# monitor the celery queues with flower, no caching enabled
location /flower/ {
proxy_pass http://flower:8888;
diff --git a/nginx/production b/nginx/production
index 9018ab9de..841ed8afa 100644
--- a/nginx/production
+++ b/nginx/production
@@ -93,15 +93,28 @@ server {
# proxy_pass http://web;
# }
#
-# # directly serve images and static files from the
+# # directly serve static files from the
# # bookwyrm filesystem using sendfile.
# # make the logs quieter by not reporting these requests
-# location ~ ^/(images|static)/ {
+# location ~ ^/static/ {
# root /app;
# try_files $uri =404;
# add_header X-Cache-Status STATIC;
# access_log off;
# }
+
+# # same with image files not in static folder
+# location ~ \.(bmp|ico|jpg|jpeg|png|svg|tif|tiff|webp)$ {
+# root /app;
+# try_files $uri =404;
+# add_header X-Cache-Status STATIC;
+# access_log off;
+# }
+
+# # block access to any non-image files from images
+# location ~ ^/images/ {
+# return 403;
+# }
#
# # monitor the celery queues with flower, no caching enabled
# location /flower/ {
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..292ca8c41
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,2 @@
+[tool.black]
+required-version = "22"
diff --git a/pytest.ini b/pytest.ini
index b50efd602..18c955032 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -11,6 +11,7 @@ env =
DEBUG = false
USE_HTTPS = true
DOMAIN = your.domain.here
+ ALLOWED_HOSTS = your.domain.here
BOOKWYRM_DATABASE_BACKEND = postgres
MEDIA_ROOT = images/
CELERY_BROKER = ""
diff --git a/redis.conf b/redis.conf
index 2a417579f..79d6804f5 100644
--- a/redis.conf
+++ b/redis.conf
@@ -2,6 +2,9 @@ bind 127.0.0.1 ::1
protected-mode yes
port 6379
+auto-aof-rewrite-percentage 50
+auto-aof-rewrite-min-size 128mb
+
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
diff --git a/requirements.txt b/requirements.txt
index 6509effc7..6b3d838bf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,57 +1,61 @@
-aiohttp==3.9.0
+aiohttp==3.9.2
bleach==5.0.1
-celery==5.2.7
-colorthief==0.2.1
-Django==3.2.23
-django-celery-beat==2.4.0
+boto3==1.26.57
bw-file-resubmit==0.6.0rc2
-django-compressor==4.3.1
+celery==5.3.1
+colorthief==0.2.1
+Django==3.2.25
+django-celery-beat==2.5.0
+django-compressor==4.4
+django-csp==3.7
django-imagekit==4.1.0
django-model-utils==4.3.1
+django-pgtrigger==4.11.0
+django-redis==5.2.0
django-sass-processor==1.2.2
-django-csp==3.7
-environs==9.5.0
-flower==1.2.0
-libsass==0.22.0
-Markdown==3.4.1
-Pillow==10.0.1
-psycopg2==2.9.5
-pycryptodome==3.19.1
-python-dateutil==2.8.2
-redis==4.5.4
-requests==2.31.0
-responses==0.22.0
-pytz>=2022.7
-boto3==1.26.57
django-storages==1.13.2
django-storages[azure]
-django-redis==5.2.0
+environs==9.5.0
+flower==2.0.0
+grpcio==1.57.0 # Not a direct dependency, pinned to get a security fix
+libsass==0.22.0
+Markdown==3.4.1
opentelemetry-api==1.16.0
opentelemetry-exporter-otlp-proto-grpc==1.16.0
opentelemetry-instrumentation-celery==0.37b0
opentelemetry-instrumentation-django==0.37b0
opentelemetry-instrumentation-psycopg2==0.37b0
opentelemetry-sdk==1.16.0
+Pillow==10.2.0
protobuf==3.20.*
+psycopg2==2.9.5
+pycryptodome==3.19.1
pyotp==2.8.0
+python-dateutil==2.8.2
+pytz>=2022.7
qrcode==7.3.1
+redis==4.5.4
+requests==2.31.0
+responses==0.22.0
+setuptools>=65.5.1 # Not a direct dependency, pinned to get a security fix
+tornado==6.3.3 # Not a direct dependency, pinned to get a security fix
# Dev
-pytest-django==4.1.0
-pytest==6.1.2
+black==22.*
+celery-types==0.18.0
+django-stubs[compatible-mypy]==4.2.4
+mypy==1.5.1
+pylint==2.15.0
+pytest==6.2.5
pytest-cov==2.10.1
+pytest-django==4.1.0
pytest-env==0.6.2
pytest-xdist==2.3.0
pytidylib==0.3.2
-pylint==2.14.0
-mypy==1.5.1
-celery-types==0.18.0
-django-stubs[compatible-mypy]==4.2.4
types-bleach==6.0.0.4
types-dataclasses==0.6.6
types-Markdown==3.4.2.10
-types-Pillow==10.0.0.3
+types-Pillow==10.2.0.20240311
types-psycopg2==2.9.21.11
types-python-dateutil==2.8.19.14
types-requests==2.31.0.2
-types-requests==2.31.0.2
diff --git a/static/.gitkeep b/static/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/update.sh b/update.sh
deleted file mode 100755
index 727ce1b24..000000000
--- a/update.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-# determine inital and target versions
-initial_version="`./bw-dev runweb python manage.py instance_version --current`"
-target_version="`./bw-dev runweb python manage.py instance_version --target`"
-
-initial_version="`echo $initial_version | tail -n 1 | xargs`"
-target_version="`echo $target_version | tail -n 1 | xargs`"
-if [[ "$initial_version" = "$target_version" ]]; then
- echo "Already up to date; version $initial_version"
- exit
-fi
-
-echo "---------------------------------------"
-echo "Updating from version: $initial_version"
-echo ".......... to version: $target_version"
-echo "---------------------------------------"
-
-function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
-
-# execute scripts between initial and target
-for version in `ls -A updates/ | sort -V `; do
- if version_gt $initial_version $version; then
- # too early
- continue
- fi
- if version_gt $version $target_version; then
- # too late
- continue
- fi
- echo "Running tasks for version $version"
- ./updates/$version
-done
-
-./bw-dev runweb python manage.py instance_version --update
-echo "✨ ----------- Done! --------------- ✨"