improve index and api for localized title

This commit is contained in:
Your Name 2024-07-13 16:19:45 -04:00 committed by Henri Dickson
parent cc239d24f8
commit 18e0d78be3
12 changed files with 338 additions and 210 deletions

View file

@ -23,6 +23,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from loguru import logger
from ninja import Field
from catalog.common import (
BaseSchema,
@ -36,18 +37,23 @@ from catalog.common import (
PrimaryLookupIdDescriptor,
jsondata,
)
from catalog.common.models import SCRIPT_CHOICES
from catalog.common.models import (
LOCALE_CHOICES_JSONFORM,
SCRIPT_CHOICES,
LanguageListField,
)
from common.models.lang import get_current_locales
from common.models.misc import uniq
from .utils import *
class EditionInSchema(ItemInSchema):
subtitle: str | None = None
subtitle: str | None = Field(default=None, alias="display_subtitle")
orig_title: str | None = None
author: list[str]
translator: list[str]
language: str | None = None
language: list[str]
pub_house: str | None = None
pub_year: int | None = None
pub_month: int | None = None
@ -63,6 +69,45 @@ class EditionSchema(EditionInSchema, BaseSchema):
pass
EDITION_LOCALIZED_TITLE_SCHEMA = {
"type": "list",
"items": {
"type": "dict",
"keys": {
"lang": {
"type": "string",
"title": _("locale"),
"choices": LOCALE_CHOICES_JSONFORM,
},
"text": {"type": "string", "title": _("text content")},
},
"required": ["lang", "s"],
},
"minItems": 1,
"maxItems": 1,
# "uniqueItems": True,
}
EDITION_LOCALIZED_SUBTITLE_SCHEMA = {
"type": "list",
"items": {
"type": "dict",
"keys": {
"lang": {
"type": "string",
"title": _("locale"),
"choices": LOCALE_CHOICES_JSONFORM,
},
"text": {"type": "string", "title": _("text content")},
},
"required": ["lang", "s"],
},
"minItems": 0,
"maxItems": 1,
# "uniqueItems": True,
}
class Edition(Item):
if TYPE_CHECKING:
works: "models.ManyToManyField[Work, Edition]"
@ -76,8 +121,10 @@ class Edition(Item):
# goodreads = LookupIdDescriptor(IdType.Goodreads)
METADATA_COPY_LIST = [
"title",
"subtitle",
"localized_title",
"localized_subtitle",
# "title",
# "subtitle",
"author",
"pub_house",
"pub_year",
@ -94,9 +141,18 @@ class Edition(Item):
"localized_description",
"contents",
]
subtitle = jsondata.CharField(
_("subtitle"), null=True, blank=True, default=None, max_length=500
# force Edition to have only one title
localized_title_schema = EDITION_LOCALIZED_TITLE_SCHEMA
localized_subtitle = jsondata.JSONField(
verbose_name=_("subtitle"),
null=False,
blank=True,
default=list,
schema=EDITION_LOCALIZED_SUBTITLE_SCHEMA,
)
# subtitle = jsondata.CharField(
# _("subtitle"), null=True, blank=True, default=None, max_length=500
# )
orig_title = jsondata.CharField(
_("original title"), null=True, blank=True, default=None, max_length=500
)
@ -114,14 +170,7 @@ class Edition(Item):
blank=True,
default=list,
)
language = jsondata.CharField(
_("language"),
null=False,
blank=True,
default=None,
max_length=500,
choices=SCRIPT_CHOICES,
)
language = LanguageListField()
pub_house = jsondata.CharField(
_("publishing house"), null=True, blank=False, default=None, max_length=500
)
@ -148,6 +197,13 @@ class Edition(Item):
price = jsondata.CharField(_("price"), null=True, blank=True, max_length=500)
imprint = jsondata.CharField(_("imprint"), null=True, blank=True, max_length=500)
def get_localized_subtitle(self) -> str | None:
return self.localized_title[0]["text"] if self.localized_subtitle else None
@property
def display_subtitle(self) -> str | None:
return self.get_localized_subtitle()
@property
def isbn10(self):
return isbn_13_to_10(self.isbn)
@ -265,6 +321,7 @@ class Work(Item):
douban_work = PrimaryLookupIdDescriptor(IdType.DoubanBook_Work)
goodreads_work = PrimaryLookupIdDescriptor(IdType.Goodreads_Work)
editions = models.ManyToManyField(Edition, related_name="works")
language = LanguageListField()
author = jsondata.ArrayField(
verbose_name=_("author"),
base_field=models.CharField(max_length=500),
@ -272,18 +329,18 @@ class Work(Item):
blank=True,
default=list,
)
other_title = jsondata.ArrayField(
verbose_name=_("other title"),
base_field=models.CharField(blank=True, default="", max_length=200),
null=True,
blank=True,
default=list,
)
# other_title = jsondata.ArrayField(
# verbose_name=_("other title"),
# base_field=models.CharField(blank=True, default="", max_length=200),
# null=True,
# blank=True,
# default=list,
# )
METADATA_COPY_LIST = [
"title",
"other_title",
"localized_title",
"author",
"brief",
"language",
"localized_description",
]
# TODO: we have many duplicates due to 302
# a lazy fix is to remove smaller DoubanBook_Work ids

View file

@ -15,6 +15,7 @@ from django.db.models import DEFERRED, fields # type:ignore
from django.utils import dateparse, timezone
from django.utils.encoding import force_bytes
from django.utils.translation import gettext_lazy as _
from django_jsonform.forms.fields import JSONFormField as DJANGO_JSONFormField
# from django.db.models import JSONField as DJANGO_JSONField
# from jsoneditor.fields.django3_jsonfield import JSONField as DJANGO_JSONField
@ -24,6 +25,20 @@ from django_jsonform.models.fields import JSONField as DJANGO_JSONField
from loguru import logger
class Patched_DJANGO_JSONField(DJANGO_JSONField):
def formfield(self, **kwargs):
schema = getattr(self.model, self.attname + "_schema", self.schema)
return super().formfield(
**{
"form_class": DJANGO_JSONFormField,
"schema": schema,
"model_name": self.model.__name__,
"file_handler": self.file_handler,
**kwargs,
}
)
def _get_crypter():
configured_keys = [settings.SECRET_KEY] + settings.SECRET_KEY_FALLBACKS
keys = [Fernet(b64encode(sha256(force_bytes(k)).digest())) for k in configured_keys]
@ -299,7 +314,7 @@ class ArrayField(JSONFieldMixin, DJANGO_ArrayField):
return []
class JSONField(JSONFieldMixin, DJANGO_JSONField):
class JSONField(JSONFieldMixin, Patched_DJANGO_JSONField):
pass

View file

@ -268,13 +268,15 @@ class LocalizedTitleSchema(Schema):
class ItemInSchema(Schema):
title: str
brief: str
title: str = Field(alias="display_title")
description: str = Field(default=None, alias="display_description")
localized_title: list[LocalizedTitleSchema] = []
localized_description: list[LocalizedTitleSchema] = []
cover_image_url: str | None
rating: float | None
rating_count: int | None
# brief is deprecated
brief: str = Field(deprecated=True, alias="display_description")
class ItemSchema(BaseSchema, ItemInSchema):
@ -296,13 +298,14 @@ LOCALIZED_TITLE_SCHEMA = {
"keys": {
"lang": {
"type": "string",
"title": _("language"),
"title": _("locale"),
"choices": LOCALE_CHOICES_JSONFORM,
},
"text": {"type": "string", "title": _("content")},
"text": {"type": "string", "title": _("text content")},
},
"required": ["lang", "s"],
},
"minItems": 1,
"uniqueItems": True,
}
@ -313,10 +316,14 @@ LOCALIZED_DESCRIPTION_SCHEMA = {
"keys": {
"lang": {
"type": "string",
"title": _("language"),
"title": _("locale"),
"choices": LOCALE_CHOICES_JSONFORM,
},
"text": {"type": "string", "title": _("content"), "widget": "textarea"},
"text": {
"type": "string",
"title": _("text content"),
"widget": "textarea",
},
},
"required": ["lang", "s"],
},
@ -669,8 +676,8 @@ class Item(PolymorphicModel):
self.primary_lookup_id_value = v
METADATA_COPY_LIST = [
"title",
"brief",
# "title",
# "brief",
"localized_title",
"localized_description",
] # list of metadata keys to copy from resource to item

View file

@ -43,7 +43,6 @@ class Game(Item):
# "brief",
# "other_title",
"localized_title",
"localized_description",
"designer",
"artist",
"developer",
@ -53,6 +52,7 @@ class Game(Item):
"genre",
"platform",
"official_site",
"localized_description",
]
other_title = jsondata.ArrayField(

View file

@ -1,4 +1,5 @@
import pprint
import re
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
@ -51,20 +52,36 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS(f"Done."))
def localize(self):
for i in tqdm(Item.objects.all()):
for i in tqdm(
Item.objects.filter(is_deleted=False, merged_to_item__isnull=True)
):
localized_title = [{"lang": detect_language(i.title), "text": i.title}]
if hasattr(i, "orig_title") and i.orig_title: # type:ignore
localized_title += [
{
"lang": detect_language(i.orig_title), # type:ignore
"text": i.orig_title, # type:ignore
}
]
if hasattr(i, "other_title") and i.other_title: # type:ignore
for title in i.other_title: # type:ignore
localized_title += [{"lang": detect_language(title), "text": title}]
localized_desc = [{"lang": detect_language(i.brief), "text": i.brief}]
if i.__class__ != Edition:
if hasattr(i, "orig_title") and i.orig_title: # type:ignore
localized_title += [
{
"lang": detect_language(i.orig_title), # type:ignore
"text": i.orig_title, # type:ignore
}
]
if hasattr(i, "other_title") and i.other_title: # type:ignore
for title in i.other_title: # type:ignore
localized_title += [
{"lang": detect_language(title), "text": title}
]
else:
# Edition has no other_title
subtitle = i.metadata.get("subtitle")
i.metadata["localized_subtitle"] = (
[{"lang": detect_language(subtitle), "text": subtitle}]
if subtitle
else []
)
lang = i.metadata.get("language")
if isinstance(lang, str):
i.metadata["language"] = [lang]
i.localized_title = uniq(localized_title)
localized_desc = [{"lang": detect_language(i.brief), "text": i.brief}]
i.localized_description = localized_desc
i.save(update_fields=["metadata"])

View file

@ -44,10 +44,10 @@ class Movie(Item):
douban_movie = PrimaryLookupIdDescriptor(IdType.DoubanMovie)
METADATA_COPY_LIST = [
"title",
# "title",
# "other_title",
"localized_title",
"orig_title",
# "other_title",
"director",
"playwright",
"actor",

View file

@ -2,6 +2,8 @@ from typing import TYPE_CHECKING
from django.db import models
from django.utils.translation import gettext_lazy as _
from ninja import Field
from typing_extensions import deprecated
from catalog.common import (
BaseSchema,
@ -20,8 +22,11 @@ from catalog.common.models import LanguageListField
class PodcastInSchema(ItemInSchema):
genre: list[str]
hosts: list[str]
host: list[str]
language: list[str]
official_site: str | None = None
# hosts is deprecated
hosts: list[str] = Field(deprecated=True, alias="host")
class PodcastSchema(PodcastInSchema, BaseSchema):
@ -61,11 +66,11 @@ class Podcast(Item):
# "title",
# "brief",
"localized_title",
"localized_description",
"language",
"hosts",
"genre",
"official_site",
"localized_description",
]
@classmethod

View file

@ -16,10 +16,9 @@ from typesense.exceptions import ObjectNotFound
from catalog.models import Item
SEARCHABLE_ATTRIBUTES = [
"title",
"localized_title",
"localized_subtitle",
"orig_title",
"other_title",
"subtitle",
"artist",
"author",
"translator",
@ -145,23 +144,29 @@ class Indexer:
{"name": "author", "optional": True, "locale": "zh", "type": "string[]"},
{"name": "orig_title", "optional": True, "locale": "zh", "type": "string"},
{"name": "pub_house", "optional": True, "locale": "zh", "type": "string"},
{"name": "title", "optional": True, "locale": "zh", "type": "string"},
# {"name": "title", "optional": True, "locale": "zh", "type": "string"},
{
"name": "localized_title",
"optional": True,
"locale": "zh",
"type": "string[]",
},
# {"name": "subtitle", "optional": True, "locale": "zh", "type": "string"},
{
"name": "localized_subtitle",
"optional": True,
"locale": "zh",
"type": "string[]",
},
{
"name": "translator",
"optional": True,
"locale": "zh",
"type": "string[]",
},
{"name": "subtitle", "optional": True, "locale": "zh", "type": "string"},
{"name": "artist", "optional": True, "locale": "zh", "type": "string[]"},
{"name": "company", "optional": True, "locale": "zh", "type": "string[]"},
{"name": "developer", "optional": True, "locale": "zh", "type": "string[]"},
{
"name": "other_title",
"optional": True,
"locale": "zh",
"type": "string[]",
},
{"name": "publisher", "optional": True, "locale": "zh", "type": "string[]"},
{"name": "actor", "optional": True, "locale": "zh", "type": "string[]"},
{"name": "director", "optional": True, "locale": "zh", "type": "string[]"},
@ -252,7 +257,8 @@ class Indexer:
model.indexable_fields.append(field.name)
elif type in INDEXABLE_TIME_TYPES:
model.indexable_fields_time.append(field.name)
elif type in INDEXABLE_DICT_TYPES:
elif type in INDEXABLE_DICT_TYPES and field.name != "metadata":
# ignore metadata since it holds other fields
model.indexable_fields_dict.append(field.name)
elif type in INDEXABLE_FLOAT_TYPES:
model.indexable_fields_float.append(field.name)
@ -287,9 +293,8 @@ class Indexer:
for field in obj.__class__.indexable_fields_float:
item[field] = float(getattr(obj, field)) if getattr(obj, field) else None
for field in obj.__class__.indexable_fields_dict:
d = getattr(obj, field)
if d.__class__ is dict:
item.update(d)
if field.startswith("localized_"):
item[field] = [t["text"] for t in getattr(obj, field, [])]
item["id"] = obj.uuid
item["category"] = obj.category.value
@ -302,7 +307,6 @@ class Indexer:
}
# typesense requires primary key to be named 'id', type string
item["rating_count"] = obj.rating_count
return item
@classmethod

View file

@ -270,11 +270,12 @@ class TVSeason(Item):
)
METADATA_COPY_LIST = [
"title",
# "title",
"localized_title",
"season_number",
"episode_count",
"orig_title",
"other_title",
# "other_title",
"director",
"playwright",
"actor",
@ -286,7 +287,8 @@ class TVSeason(Item):
"year",
"duration",
"single_episode_length",
"brief",
"localized_description",
# "brief",
]
orig_title = jsondata.CharField(
verbose_name=_("original title"), blank=True, default="", max_length=500

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-13 01:27-0400\n"
"POT-Creation-Date: 2024-07-13 16:14-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -27,74 +27,70 @@ msgstr "简体中文"
msgid "Traditional Chinese"
msgstr "繁体中文"
#: catalog/book/models.py:98
#: catalog/book/models.py:80 catalog/book/models.py:99
#: catalog/common/models.py:301 catalog/common/models.py:319
msgid "locale"
msgstr "区域语言"
#: catalog/book/models.py:83 catalog/book/models.py:102
#: catalog/common/models.py:304 catalog/common/models.py:324
msgid "text content"
msgstr "文本内容"
#: catalog/book/models.py:148
msgid "subtitle"
msgstr "副标题"
#: catalog/book/models.py:101 catalog/movie/models.py:68
#: catalog/book/models.py:158 catalog/movie/models.py:68
#: catalog/performance/models.py:257 catalog/tv/models.py:137
#: catalog/tv/models.py:292
#: catalog/tv/models.py:294
msgid "original title"
msgstr "原名"
#: catalog/book/models.py:104 catalog/book/models.py:269
#: catalog/book/models.py:161 catalog/book/models.py:327
msgid "author"
msgstr "作者"
#: catalog/book/models.py:111
#: catalog/book/models.py:168
msgid "translator"
msgstr "译者"
#: catalog/book/models.py:118 catalog/common/models.py:299
#: catalog/common/models.py:316 catalog/common/models.py:329
#: catalog/templates/edition.html:47 catalog/tv/models.py:372
#: users/models/user.py:114
msgid "language"
msgstr "语言"
#: catalog/book/models.py:126 catalog/templates/edition.html:26
#: catalog/book/models.py:176 catalog/templates/edition.html:26
msgid "publishing house"
msgstr "出版社"
#: catalog/book/models.py:129
#: catalog/book/models.py:179
msgid "publication year"
msgstr "发行年份"
#: catalog/book/models.py:135
#: catalog/book/models.py:185
msgid "publication month"
msgstr "发行月份"
#: catalog/book/models.py:141 catalog/templates/edition.html:52
#: catalog/book/models.py:191 catalog/templates/edition.html:52
msgid "binding"
msgstr "装订"
#: catalog/book/models.py:143
#: catalog/book/models.py:193
msgid "pages"
msgstr "页数"
#: catalog/book/models.py:145 catalog/templates/edition.html:42
#: catalog/book/models.py:195 catalog/templates/edition.html:42
msgid "series"
msgstr "丛书"
#: catalog/book/models.py:147
#: catalog/book/models.py:197
msgid "contents"
msgstr "目录"
#: catalog/book/models.py:148 catalog/templates/edition.html:57
#: catalog/book/models.py:198 catalog/templates/edition.html:57
msgid "price"
msgstr "价格"
#: catalog/book/models.py:149 catalog/templates/edition.html:31
#: catalog/book/models.py:199 catalog/templates/edition.html:31
msgid "imprint"
msgstr "出品方"
#: catalog/book/models.py:276 catalog/game/models.py:60
#: catalog/movie/models.py:71 catalog/music/models.py:87
#: catalog/performance/models.py:115 catalog/performance/models.py:260
#: catalog/tv/models.py:141 catalog/tv/models.py:295
msgid "other title"
msgstr "其它标题"
#: catalog/common/models.py:37
msgid "Unknown"
msgstr "未知"
@ -377,60 +373,68 @@ msgstr "播客"
msgid "FanFic"
msgstr "网文"
#: catalog/common/models.py:302 catalog/common/models.py:319
msgid "content"
msgstr ""
#: catalog/common/models.py:336 catalog/templates/edition.html:47
#: catalog/tv/models.py:374 users/models/user.py:114
msgid "language"
msgstr "语言"
#: catalog/common/models.py:352 catalog/common/models.py:380
#: catalog/common/models.py:359 catalog/common/models.py:387
#: journal/models/collection.py:52
msgid "title"
msgstr "标题"
#: catalog/common/models.py:353 catalog/common/models.py:388
#: catalog/common/models.py:360 catalog/common/models.py:395
#: journal/models/collection.py:53
msgid "description"
msgstr "描述"
#: catalog/common/models.py:355 catalog/forms.py:27
#: catalog/common/models.py:362 catalog/forms.py:27
msgid "Primary ID Type"
msgstr "主要标识类型"
#: catalog/common/models.py:358 catalog/forms.py:32
#: catalog/common/models.py:365 catalog/forms.py:32
msgid "Primary ID Value"
msgstr "主要标识数据"
#: catalog/common/models.py:364
#: catalog/common/models.py:371
msgid "metadata"
msgstr "元数据"
#: catalog/common/models.py:366
#: catalog/common/models.py:373
msgid "cover"
msgstr "封面"
#: catalog/common/models.py:769
#: catalog/common/models.py:776
msgid "source site"
msgstr "来源站点"
#: catalog/common/models.py:771
#: catalog/common/models.py:778
msgid "ID on source site"
msgstr "来源站点标识"
#: catalog/common/models.py:773
#: catalog/common/models.py:780
msgid "source url"
msgstr "来源站点网址"
#: catalog/common/models.py:789
#: catalog/common/models.py:796
msgid "IdType of the source site"
msgstr "来源站点的主要标识类型"
#: catalog/common/models.py:795
#: catalog/common/models.py:802
msgid "Primary Id on the source site"
msgstr "来源站点的主要标识数据"
#: catalog/common/models.py:798
#: catalog/common/models.py:805
msgid "url to the resource"
msgstr "指向外部资源的网址"
#: catalog/game/models.py:60 catalog/movie/models.py:71
#: catalog/music/models.py:87 catalog/performance/models.py:115
#: catalog/performance/models.py:260 catalog/tv/models.py:141
#: catalog/tv/models.py:297
msgid "other title"
msgstr "其它标题"
#: catalog/game/models.py:68
msgid "designer"
msgstr "设计者"
@ -451,7 +455,7 @@ msgstr "出版发行"
msgid "year of publication"
msgstr "发行年份"
#: catalog/game/models.py:103 catalog/podcast/models.py:103
#: catalog/game/models.py:103 catalog/podcast/models.py:108
msgid "date of publication"
msgstr "发行日期"
@ -461,8 +465,8 @@ msgid "YYYY-MM-DD"
msgstr ""
#: catalog/game/models.py:112 catalog/movie/models.py:99
#: catalog/performance/models.py:122 catalog/podcast/models.py:41
#: catalog/tv/models.py:168 catalog/tv/models.py:323
#: catalog/performance/models.py:122 catalog/podcast/models.py:46
#: catalog/tv/models.py:168 catalog/tv/models.py:325
msgid "genre"
msgstr "类型"
@ -472,30 +476,30 @@ msgstr "平台"
#: catalog/game/models.py:126 catalog/movie/models.py:134
#: catalog/performance/models.py:206 catalog/performance/models.py:344
#: catalog/podcast/models.py:57 catalog/templates/game.html:29
#: catalog/podcast/models.py:62 catalog/templates/game.html:29
#: catalog/templates/movie.html:58 catalog/templates/performance.html:33
#: catalog/templates/performanceproduction.html:33
#: catalog/templates/podcast.html:20 catalog/templates/tvseason.html:75
#: catalog/templates/tvshow.html:70 catalog/tv/models.py:203
#: catalog/tv/models.py:358
#: catalog/tv/models.py:360
msgid "website"
msgstr "网站"
#: catalog/movie/models.py:78 catalog/performance/models.py:130
#: catalog/performance/models.py:268 catalog/tv/models.py:147
#: catalog/tv/models.py:302
#: catalog/tv/models.py:304
msgid "director"
msgstr "导演"
#: catalog/movie/models.py:85 catalog/performance/models.py:137
#: catalog/performance/models.py:275 catalog/tv/models.py:154
#: catalog/tv/models.py:309
#: catalog/tv/models.py:311
msgid "playwright"
msgstr "编剧"
#: catalog/movie/models.py:92 catalog/performance/models.py:165
#: catalog/performance/models.py:303 catalog/tv/models.py:161
#: catalog/tv/models.py:316
#: catalog/tv/models.py:318
msgid "actor"
msgstr "演员"
@ -507,32 +511,32 @@ msgstr "演员"
msgid "release date"
msgstr "发布日期"
#: catalog/movie/models.py:118 catalog/tv/models.py:342
#: catalog/movie/models.py:118 catalog/tv/models.py:344
#: journal/templates/_sidebar_user_mark_list.html:62
msgid "date"
msgstr "日期"
#: catalog/movie/models.py:119 catalog/performance/models.py:82
#: catalog/tv/models.py:343
#: catalog/tv/models.py:345
msgid "required"
msgstr "必填"
#: catalog/movie/models.py:123 catalog/tv/models.py:347
#: catalog/movie/models.py:123 catalog/tv/models.py:349
msgid "region or event"
msgstr "地区或类型"
#: catalog/movie/models.py:125 catalog/tv/models.py:194
#: catalog/tv/models.py:349
#: catalog/tv/models.py:351
msgid "Germany or Toronto International Film Festival"
msgstr "德国或多伦多国际电影节"
#: catalog/movie/models.py:137 catalog/tv/models.py:206
#: catalog/tv/models.py:361
#: catalog/tv/models.py:363
msgid "region"
msgstr "地区"
#: catalog/movie/models.py:148 catalog/tv/models.py:218
#: catalog/tv/models.py:382
#: catalog/tv/models.py:384
msgid "year"
msgstr "年份"
@ -621,7 +625,7 @@ msgstr "上演日期"
msgid "closing date"
msgstr "结束日期"
#: catalog/podcast/models.py:51
#: catalog/podcast/models.py:56
msgid "host"
msgstr "主播"
@ -670,17 +674,17 @@ msgid "hide this tooltip"
msgstr "不再提示"
#: catalog/templates/_item_comments.html:82
#: catalog/templates/_item_comments_by_episode.html:78
#: catalog/templates/_item_comments_by_episode.html:80
#: catalog/templates/_item_reviews.html:43
#: catalog/templates/podcast_episode_data.html:41
msgid "show more"
msgstr "显示更多"
#: catalog/templates/_item_comments.html:86
#: catalog/templates/_item_comments_by_episode.html:82
#: catalog/templates/_item_comments_by_episode.html:84
#: catalog/templates/_item_reviews.html:47
#: catalog/templates/podcast_episode_data.html:44
#: social/templates/events.html:43 social/templates/feed_events.html:133
#: social/templates/events.html:43 social/templates/feed_events.html:135
msgid "nothing more."
msgstr "没有更多内容了。"
@ -1111,7 +1115,7 @@ msgid "Popular Tags"
msgstr "热门标签"
#: catalog/templates/discover.html:177 catalog/templates/item_base.html:236
#: catalog/templates/item_mark_list.html:54
#: catalog/templates/item_mark_list.html:56
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:90
#: common/templates/_sidebar_anonymous.html:43
#: common/templates/_sidebar_anonymous.html:58
@ -1348,7 +1352,7 @@ msgstr "集数"
msgid "Editions"
msgstr "版本"
#: catalog/tv/models.py:175 catalog/tv/models.py:330
#: catalog/tv/models.py:175 catalog/tv/models.py:332
msgid "show time"
msgstr "上映时间"
@ -1360,16 +1364,16 @@ msgstr "日期"
msgid "Region or Event"
msgstr "地区或场合"
#: catalog/tv/models.py:220 catalog/tv/models.py:384
#: catalog/tv/models.py:220 catalog/tv/models.py:386
msgid "episode length"
msgstr "单集长度"
#: catalog/tv/models.py:407
#: catalog/tv/models.py:409
#, python-brace-format
msgid "{show_title} S{season_number}"
msgstr "{show_title} 第{season_number}季"
#: catalog/tv/models.py:459
#: catalog/tv/models.py:461
#, python-brace-format
msgid "{season_title} E{episode_number}"
msgstr "{season_title} 第{episode_number}集"
@ -3970,7 +3974,7 @@ msgstr "标记"
msgid "wrote a note"
msgstr "写了笔记"
#: social/templates/feed_events.html:137
#: social/templates/feed_events.html:139
#, python-format
msgid "Find and mark some books/movies/podcasts/games, <a href=\"%(import_url)s\">import your data</a> from Goodreads/Letterboxd/Douban, follow some fellow %(site_name)s users on the fediverse, so their recent activities and yours will show up here."
msgstr "搜索并标记一些书影音/播客/游戏,<a href=\"%(import_url)s\">导入你的豆瓣、Letterboxd或Goodreads记录</a>,去联邦宇宙(长毛象)关注一些正在使用%(site_name)s的用户这里就会显示你和她们的近期动态。"

View file

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-13 01:27-0400\n"
"POT-Creation-Date: 2024-07-13 16:14-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -27,74 +27,70 @@ msgstr "簡體中文"
msgid "Traditional Chinese"
msgstr "繁體中文"
#: catalog/book/models.py:98
#: catalog/book/models.py:80 catalog/book/models.py:99
#: catalog/common/models.py:301 catalog/common/models.py:319
msgid "locale"
msgstr "區域語言"
#: catalog/book/models.py:83 catalog/book/models.py:102
#: catalog/common/models.py:304 catalog/common/models.py:324
msgid "text content"
msgstr "文本內容"
#: catalog/book/models.py:148
msgid "subtitle"
msgstr "副標題"
#: catalog/book/models.py:101 catalog/movie/models.py:68
#: catalog/book/models.py:158 catalog/movie/models.py:68
#: catalog/performance/models.py:257 catalog/tv/models.py:137
#: catalog/tv/models.py:292
#: catalog/tv/models.py:294
msgid "original title"
msgstr "原名"
#: catalog/book/models.py:104 catalog/book/models.py:269
#: catalog/book/models.py:161 catalog/book/models.py:327
msgid "author"
msgstr "作者"
#: catalog/book/models.py:111
#: catalog/book/models.py:168
msgid "translator"
msgstr "譯者"
#: catalog/book/models.py:118 catalog/common/models.py:299
#: catalog/common/models.py:316 catalog/common/models.py:329
#: catalog/templates/edition.html:47 catalog/tv/models.py:372
#: users/models/user.py:114
msgid "language"
msgstr "語言"
#: catalog/book/models.py:126 catalog/templates/edition.html:26
#: catalog/book/models.py:176 catalog/templates/edition.html:26
msgid "publishing house"
msgstr "出版社"
#: catalog/book/models.py:129
#: catalog/book/models.py:179
msgid "publication year"
msgstr "發行年份"
#: catalog/book/models.py:135
#: catalog/book/models.py:185
msgid "publication month"
msgstr "發行月份"
#: catalog/book/models.py:141 catalog/templates/edition.html:52
#: catalog/book/models.py:191 catalog/templates/edition.html:52
msgid "binding"
msgstr "裝訂"
#: catalog/book/models.py:143
#: catalog/book/models.py:193
msgid "pages"
msgstr "頁數"
#: catalog/book/models.py:145 catalog/templates/edition.html:42
#: catalog/book/models.py:195 catalog/templates/edition.html:42
msgid "series"
msgstr "叢書"
#: catalog/book/models.py:147
#: catalog/book/models.py:197
msgid "contents"
msgstr "目錄"
#: catalog/book/models.py:148 catalog/templates/edition.html:57
#: catalog/book/models.py:198 catalog/templates/edition.html:57
msgid "price"
msgstr "價格"
#: catalog/book/models.py:149 catalog/templates/edition.html:31
#: catalog/book/models.py:199 catalog/templates/edition.html:31
msgid "imprint"
msgstr "出品方"
#: catalog/book/models.py:276 catalog/game/models.py:60
#: catalog/movie/models.py:71 catalog/music/models.py:87
#: catalog/performance/models.py:115 catalog/performance/models.py:260
#: catalog/tv/models.py:141 catalog/tv/models.py:295
msgid "other title"
msgstr "其它標題"
#: catalog/common/models.py:37
msgid "Unknown"
msgstr "未知"
@ -377,60 +373,68 @@ msgstr "播客"
msgid "FanFic"
msgstr "網文"
#: catalog/common/models.py:302 catalog/common/models.py:319
msgid "content"
msgstr ""
#: catalog/common/models.py:336 catalog/templates/edition.html:47
#: catalog/tv/models.py:374 users/models/user.py:114
msgid "language"
msgstr "語言"
#: catalog/common/models.py:352 catalog/common/models.py:380
#: catalog/common/models.py:359 catalog/common/models.py:387
#: journal/models/collection.py:52
msgid "title"
msgstr "標題"
#: catalog/common/models.py:353 catalog/common/models.py:388
#: catalog/common/models.py:360 catalog/common/models.py:395
#: journal/models/collection.py:53
msgid "description"
msgstr "描述"
#: catalog/common/models.py:355 catalog/forms.py:27
#: catalog/common/models.py:362 catalog/forms.py:27
msgid "Primary ID Type"
msgstr "主要標識類型"
#: catalog/common/models.py:358 catalog/forms.py:32
#: catalog/common/models.py:365 catalog/forms.py:32
msgid "Primary ID Value"
msgstr "主要標識數據"
#: catalog/common/models.py:364
#: catalog/common/models.py:371
msgid "metadata"
msgstr "元數據"
#: catalog/common/models.py:366
#: catalog/common/models.py:373
msgid "cover"
msgstr "封面"
#: catalog/common/models.py:769
#: catalog/common/models.py:776
msgid "source site"
msgstr "來源站點"
#: catalog/common/models.py:771
#: catalog/common/models.py:778
msgid "ID on source site"
msgstr "來源站點標識"
#: catalog/common/models.py:773
#: catalog/common/models.py:780
msgid "source url"
msgstr "來源站點網址"
#: catalog/common/models.py:789
#: catalog/common/models.py:796
msgid "IdType of the source site"
msgstr "來源站點的主要標識類型"
#: catalog/common/models.py:795
#: catalog/common/models.py:802
msgid "Primary Id on the source site"
msgstr "來源站點的主要標識數據"
#: catalog/common/models.py:798
#: catalog/common/models.py:805
msgid "url to the resource"
msgstr "指向外部資源的網址"
#: catalog/game/models.py:60 catalog/movie/models.py:71
#: catalog/music/models.py:87 catalog/performance/models.py:115
#: catalog/performance/models.py:260 catalog/tv/models.py:141
#: catalog/tv/models.py:297
msgid "other title"
msgstr "其它標題"
#: catalog/game/models.py:68
msgid "designer"
msgstr "設計者"
@ -451,7 +455,7 @@ msgstr "出版發行"
msgid "year of publication"
msgstr "發行年份"
#: catalog/game/models.py:103 catalog/podcast/models.py:103
#: catalog/game/models.py:103 catalog/podcast/models.py:108
msgid "date of publication"
msgstr "發行日期"
@ -461,8 +465,8 @@ msgid "YYYY-MM-DD"
msgstr ""
#: catalog/game/models.py:112 catalog/movie/models.py:99
#: catalog/performance/models.py:122 catalog/podcast/models.py:41
#: catalog/tv/models.py:168 catalog/tv/models.py:323
#: catalog/performance/models.py:122 catalog/podcast/models.py:46
#: catalog/tv/models.py:168 catalog/tv/models.py:325
msgid "genre"
msgstr "類型"
@ -472,30 +476,30 @@ msgstr "平臺"
#: catalog/game/models.py:126 catalog/movie/models.py:134
#: catalog/performance/models.py:206 catalog/performance/models.py:344
#: catalog/podcast/models.py:57 catalog/templates/game.html:29
#: catalog/podcast/models.py:62 catalog/templates/game.html:29
#: catalog/templates/movie.html:58 catalog/templates/performance.html:33
#: catalog/templates/performanceproduction.html:33
#: catalog/templates/podcast.html:20 catalog/templates/tvseason.html:75
#: catalog/templates/tvshow.html:70 catalog/tv/models.py:203
#: catalog/tv/models.py:358
#: catalog/tv/models.py:360
msgid "website"
msgstr "網站"
#: catalog/movie/models.py:78 catalog/performance/models.py:130
#: catalog/performance/models.py:268 catalog/tv/models.py:147
#: catalog/tv/models.py:302
#: catalog/tv/models.py:304
msgid "director"
msgstr "導演"
#: catalog/movie/models.py:85 catalog/performance/models.py:137
#: catalog/performance/models.py:275 catalog/tv/models.py:154
#: catalog/tv/models.py:309
#: catalog/tv/models.py:311
msgid "playwright"
msgstr "編劇"
#: catalog/movie/models.py:92 catalog/performance/models.py:165
#: catalog/performance/models.py:303 catalog/tv/models.py:161
#: catalog/tv/models.py:316
#: catalog/tv/models.py:318
msgid "actor"
msgstr "演員"
@ -507,32 +511,32 @@ msgstr "演員"
msgid "release date"
msgstr "發佈日期"
#: catalog/movie/models.py:118 catalog/tv/models.py:342
#: catalog/movie/models.py:118 catalog/tv/models.py:344
#: journal/templates/_sidebar_user_mark_list.html:62
msgid "date"
msgstr "日期"
#: catalog/movie/models.py:119 catalog/performance/models.py:82
#: catalog/tv/models.py:343
#: catalog/tv/models.py:345
msgid "required"
msgstr "必填"
#: catalog/movie/models.py:123 catalog/tv/models.py:347
#: catalog/movie/models.py:123 catalog/tv/models.py:349
msgid "region or event"
msgstr "地區或類型"
#: catalog/movie/models.py:125 catalog/tv/models.py:194
#: catalog/tv/models.py:349
#: catalog/tv/models.py:351
msgid "Germany or Toronto International Film Festival"
msgstr "德國或多倫多國際電影節"
#: catalog/movie/models.py:137 catalog/tv/models.py:206
#: catalog/tv/models.py:361
#: catalog/tv/models.py:363
msgid "region"
msgstr "地區"
#: catalog/movie/models.py:148 catalog/tv/models.py:218
#: catalog/tv/models.py:382
#: catalog/tv/models.py:384
msgid "year"
msgstr "年份"
@ -621,7 +625,7 @@ msgstr "上演日期"
msgid "closing date"
msgstr "結束日期"
#: catalog/podcast/models.py:51
#: catalog/podcast/models.py:56
msgid "host"
msgstr "主播"
@ -670,17 +674,17 @@ msgid "hide this tooltip"
msgstr "不再提示"
#: catalog/templates/_item_comments.html:82
#: catalog/templates/_item_comments_by_episode.html:78
#: catalog/templates/_item_comments_by_episode.html:80
#: catalog/templates/_item_reviews.html:43
#: catalog/templates/podcast_episode_data.html:41
msgid "show more"
msgstr "顯示更多"
#: catalog/templates/_item_comments.html:86
#: catalog/templates/_item_comments_by_episode.html:82
#: catalog/templates/_item_comments_by_episode.html:84
#: catalog/templates/_item_reviews.html:47
#: catalog/templates/podcast_episode_data.html:44
#: social/templates/events.html:43 social/templates/feed_events.html:133
#: social/templates/events.html:43 social/templates/feed_events.html:135
msgid "nothing more."
msgstr "沒有更多內容了。"
@ -1111,7 +1115,7 @@ msgid "Popular Tags"
msgstr "熱門標籤"
#: catalog/templates/discover.html:177 catalog/templates/item_base.html:236
#: catalog/templates/item_mark_list.html:54
#: catalog/templates/item_mark_list.html:56
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:90
#: common/templates/_sidebar_anonymous.html:43
#: common/templates/_sidebar_anonymous.html:58
@ -1348,7 +1352,7 @@ msgstr "集數"
msgid "Editions"
msgstr "版本"
#: catalog/tv/models.py:175 catalog/tv/models.py:330
#: catalog/tv/models.py:175 catalog/tv/models.py:332
msgid "show time"
msgstr "上映時間"
@ -1360,16 +1364,16 @@ msgstr "日期"
msgid "Region or Event"
msgstr "地區或場合"
#: catalog/tv/models.py:220 catalog/tv/models.py:384
#: catalog/tv/models.py:220 catalog/tv/models.py:386
msgid "episode length"
msgstr "單集長度"
#: catalog/tv/models.py:407
#: catalog/tv/models.py:409
#, python-brace-format
msgid "{show_title} S{season_number}"
msgstr "{show_title} 第{season_number}季"
#: catalog/tv/models.py:459
#: catalog/tv/models.py:461
#, python-brace-format
msgid "{season_title} E{episode_number}"
msgstr "{season_title} 第{episode_number}集"
@ -3970,7 +3974,7 @@ msgstr "標記"
msgid "wrote a note"
msgstr "寫了筆記"
#: social/templates/feed_events.html:137
#: social/templates/feed_events.html:139
#, python-format
msgid "Find and mark some books/movies/podcasts/games, <a href=\"%(import_url)s\">import your data</a> from Goodreads/Letterboxd/Douban, follow some fellow %(site_name)s users on the fediverse, so their recent activities and yours will show up here."
msgstr "搜索並標記一些書影音/播客/遊戲,<a href=\"%(import_url)s\">導入你的豆瓣、Letterboxd或Goodreads記錄</a>,去聯邦宇宙(長毛象)關注一些正在使用%(site_name)s的用戶這裏就會顯示你和她們的近期動態。"