Merge branch 'main' into storefront-nuxt
This commit is contained in:
commit
02c402c6de
252 changed files with 25684 additions and 13015 deletions
|
|
@ -7,7 +7,7 @@ from .models import Post, PostTag
|
||||||
|
|
||||||
|
|
||||||
@register(Post)
|
@register(Post)
|
||||||
class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc]
|
class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc, type-arg]
|
||||||
list_display = ("title", "author", "slug", "created", "modified")
|
list_display = ("title", "author", "slug", "created", "modified")
|
||||||
list_filter = ("author", "tags", "created", "modified")
|
list_filter = ("author", "tags", "created", "modified")
|
||||||
search_fields = ("title", "content", "slug")
|
search_fields = ("title", "content", "slug")
|
||||||
|
|
@ -34,7 +34,7 @@ class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, ActivationActionsMixi
|
||||||
|
|
||||||
|
|
||||||
@register(PostTag)
|
@register(PostTag)
|
||||||
class PostTagAdmin(ModelAdmin):
|
class PostTagAdmin(ModelAdmin): # type: ignore [misc, type-arg]
|
||||||
list_display = ("tag_name", "name")
|
list_display = ("tag_name", "name")
|
||||||
search_fields = ("tag_name", "name")
|
search_fields = ("tag_name", "name")
|
||||||
ordering = ("tag_name",)
|
ordering = ("tag_name",)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,44 +25,44 @@ msgstr "عنوان المنشور"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "العنوان"
|
msgstr "العنوان"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "المنشور"
|
msgstr "المنشور"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "المنشورات"
|
msgstr "المنشورات"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ملفات تخفيض السعر غير مدعومة Yer - استخدم محتوى تخفيض السعر بدلاً من ذلك!"
|
"ملفات تخفيض السعر غير مدعومة Yer - استخدم محتوى تخفيض السعر بدلاً من ذلك!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr "يجب توفير ملف ترميز أو محتوى ترميز مخفض - متنافيان"
|
msgstr "يجب توفير ملف ترميز أو محتوى ترميز مخفض - متنافيان"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "معرّف العلامة الداخلي لعلامة المنشور"
|
msgstr "معرّف العلامة الداخلي لعلامة المنشور"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "اسم العلامة"
|
msgstr "اسم العلامة"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "اسم سهل الاستخدام لعلامة المنشور"
|
msgstr "اسم سهل الاستخدام لعلامة المنشور"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "اسم عرض العلامة"
|
msgstr "اسم عرض العلامة"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "علامة المشاركة"
|
msgstr "علامة المشاركة"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "علامات المشاركة"
|
msgstr "علامات المشاركة"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,46 +25,46 @@ msgstr "Název příspěvku"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Název"
|
msgstr "Název"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Příspěvek"
|
msgstr "Příspěvek"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Příspěvky"
|
msgstr "Příspěvky"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Soubory Markdown nejsou podporovány - místo toho použijte obsah Markdown!"
|
"Soubory Markdown nejsou podporovány - místo toho použijte obsah Markdown!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"musí být poskytnut soubor markdown nebo obsah markdown - vzájemně se "
|
"musí být poskytnut soubor markdown nebo obsah markdown - vzájemně se "
|
||||||
"vylučují."
|
"vylučují."
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "interní identifikátor tagu pro tag příspěvku"
|
msgstr "interní identifikátor tagu pro tag příspěvku"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Název štítku"
|
msgstr "Název štítku"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Uživatelsky přívětivý název pro značku příspěvku"
|
msgstr "Uživatelsky přívětivý název pro značku příspěvku"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Zobrazení názvu štítku"
|
msgstr "Zobrazení názvu štítku"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Označení příspěvku"
|
msgstr "Označení příspěvku"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Štítky příspěvků"
|
msgstr "Štítky příspěvků"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,44 +25,44 @@ msgstr "Indlæggets titel"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Indlæg"
|
msgstr "Indlæg"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Indlæg"
|
msgstr "Indlæg"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "Markdown-filer understøttes ikke - brug markdown-indhold i stedet!"
|
msgstr "Markdown-filer understøttes ikke - brug markdown-indhold i stedet!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"en markdown-fil eller markdown-indhold skal leveres - gensidigt udelukkende"
|
"en markdown-fil eller markdown-indhold skal leveres - gensidigt udelukkende"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "intern tag-identifikator for indlægs-tagget"
|
msgstr "intern tag-identifikator for indlægs-tagget"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tag-navn"
|
msgstr "Tag-navn"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Brugervenligt navn til posttagget"
|
msgstr "Brugervenligt navn til posttagget"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Navn på tag-visning"
|
msgstr "Navn på tag-visning"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Tag til indlæg"
|
msgstr "Tag til indlæg"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tags til indlæg"
|
msgstr "Tags til indlæg"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "Titel des Beitrags"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Beitrag"
|
msgstr "Beitrag"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Beiträge"
|
msgstr "Beiträge"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Markdown-Dateien werden nicht unterstützt - verwenden Sie stattdessen "
|
"Markdown-Dateien werden nicht unterstützt - verwenden Sie stattdessen "
|
||||||
"Markdown-Inhalte!"
|
"Markdown-Inhalte!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"eine Markdown-Datei oder ein Markdown-Inhalt muss bereitgestellt werden - "
|
"eine Markdown-Datei oder ein Markdown-Inhalt muss bereitgestellt werden - "
|
||||||
"beide schließen sich gegenseitig aus"
|
"beide schließen sich gegenseitig aus"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "interner Tag-Bezeichner für den Post-Tag"
|
msgstr "interner Tag-Bezeichner für den Post-Tag"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tag name"
|
msgstr "Tag name"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Benutzerfreundlicher Name für das Post-Tag"
|
msgstr "Benutzerfreundlicher Name für das Post-Tag"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Tag-Anzeigename"
|
msgstr "Tag-Anzeigename"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Tag eintragen"
|
msgstr "Tag eintragen"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tags eintragen"
|
msgstr "Tags eintragen"
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
||||||
# This file is distributed under the same license as the EVIBES package.
|
# This file is distributed under the same license as the EVIBES package.
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -29,44 +29,44 @@ msgstr "Post's title"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Title"
|
msgstr "Title"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Posts"
|
msgstr "Posts"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "Markdown files are not supported yer - use markdown content instead!"
|
msgstr "Markdown files are not supported yer - use markdown content instead!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "internal tag identifier for the post tag"
|
msgstr "internal tag identifier for the post tag"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tag name"
|
msgstr "Tag name"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "User-friendly name for the post tag"
|
msgstr "User-friendly name for the post tag"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Tag display name"
|
msgstr "Tag display name"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tag"
|
msgstr "Post tag"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Post tags"
|
msgstr "Post tags"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,44 +25,44 @@ msgstr "Post's title"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Title"
|
msgstr "Title"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Posts"
|
msgstr "Posts"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "Markdown files are not supported yer - use markdown content instead!"
|
msgstr "Markdown files are not supported yer - use markdown content instead!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "internal tag identifier for the post tag"
|
msgstr "internal tag identifier for the post tag"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tag name"
|
msgstr "Tag name"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "User-friendly name for the post tag"
|
msgstr "User-friendly name for the post tag"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Tag display name"
|
msgstr "Tag display name"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tag"
|
msgstr "Post tag"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Post tags"
|
msgstr "Post tags"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,46 +25,46 @@ msgstr "Título del mensaje"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Título"
|
msgstr "Título"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Publicar en"
|
msgstr "Publicar en"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Puestos"
|
msgstr "Puestos"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"No se admiten archivos Markdown - ¡utiliza contenido Markdown en su lugar!"
|
"No se admiten archivos Markdown - ¡utiliza contenido Markdown en su lugar!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"se debe proporcionar un archivo markdown o contenido markdown - mutuamente "
|
"se debe proporcionar un archivo markdown o contenido markdown - mutuamente "
|
||||||
"excluyentes"
|
"excluyentes"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "identificador interno de la etiqueta post"
|
msgstr "identificador interno de la etiqueta post"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nombre de la etiqueta"
|
msgstr "Nombre de la etiqueta"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nombre fácil de usar para la etiqueta de la entrada"
|
msgstr "Nombre fácil de usar para la etiqueta de la entrada"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nombre de la etiqueta"
|
msgstr "Nombre de la etiqueta"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Etiqueta postal"
|
msgstr "Etiqueta postal"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Etiquetas"
|
msgstr "Etiquetas"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -28,43 +28,43 @@ msgstr ""
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "Titre du message"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titre"
|
msgstr "Titre"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Poste"
|
msgstr "Poste"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Postes"
|
msgstr "Postes"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Les fichiers Markdown ne sont pas pris en charge - utilisez plutôt du "
|
"Les fichiers Markdown ne sont pas pris en charge - utilisez plutôt du "
|
||||||
"contenu Markdown !"
|
"contenu Markdown !"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"un fichier markdown ou un contenu markdown doit être fourni - ils s'excluent "
|
"un fichier markdown ou un contenu markdown doit être fourni - ils s'excluent "
|
||||||
"mutuellement"
|
"mutuellement"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "identifiant interne de la balise post"
|
msgstr "identifiant interne de la balise post"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nom du jour"
|
msgstr "Nom du jour"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nom convivial pour la balise post"
|
msgstr "Nom convivial pour la balise post"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nom d'affichage de l'étiquette"
|
msgstr "Nom d'affichage de l'étiquette"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Tag de poste"
|
msgstr "Tag de poste"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tags de la poste"
|
msgstr "Tags de la poste"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,43 +25,43 @@ msgstr "כותרת הפוסט"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "כותרת"
|
msgstr "כותרת"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "פוסט"
|
msgstr "פוסט"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "פוסטים"
|
msgstr "פוסטים"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "קובצי Markdown אינם נתמכים עדיין - השתמש בתוכן Markdown במקום!"
|
msgstr "קובצי Markdown אינם נתמכים עדיין - השתמש בתוכן Markdown במקום!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr "יש לספק קובץ markdown או תוכן markdown - באופן בלעדי"
|
msgstr "יש לספק קובץ markdown או תוכן markdown - באופן בלעדי"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "מזהה תגיות פנימי עבור תגיות הפוסט"
|
msgstr "מזהה תגיות פנימי עבור תגיות הפוסט"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "שם היום"
|
msgstr "שם היום"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "שם ידידותי למשתמש עבור תגיות הפוסט"
|
msgstr "שם ידידותי למשתמש עבור תגיות הפוסט"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "שם תצוגה של התג"
|
msgstr "שם תצוגה של התג"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "תגית פוסט"
|
msgstr "תגית פוסט"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "תגיות פוסט"
|
msgstr "תגיות פוסט"
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
||||||
# This file is distributed under the same license as the EVIBES package.
|
# This file is distributed under the same license as the EVIBES package.
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -28,43 +28,43 @@ msgstr ""
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -28,43 +28,43 @@ msgstr ""
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "Judul postingan"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Judul"
|
msgstr "Judul"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Pos"
|
msgstr "Pos"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Posting"
|
msgstr "Posting"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"File penurunan harga tidak didukung - gunakan konten penurunan harga sebagai"
|
"File penurunan harga tidak didukung - gunakan konten penurunan harga sebagai "
|
||||||
" gantinya!"
|
"gantinya!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"file penurunan harga atau konten penurunan harga harus disediakan - tidak "
|
"file penurunan harga atau konten penurunan harga harus disediakan - tidak "
|
||||||
"boleh ada yang sama"
|
"boleh ada yang sama"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "pengidentifikasi tag internal untuk tag pos"
|
msgstr "pengidentifikasi tag internal untuk tag pos"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nama tag"
|
msgstr "Nama tag"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nama yang mudah digunakan untuk tag postingan"
|
msgstr "Nama yang mudah digunakan untuk tag postingan"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nama tampilan tag"
|
msgstr "Nama tampilan tag"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Tag pos"
|
msgstr "Tag pos"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tag pos"
|
msgstr "Tag pos"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,45 +25,45 @@ msgstr "Titolo del post"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titolo"
|
msgstr "Titolo"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Posta"
|
msgstr "Posta"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Messaggi"
|
msgstr "Messaggi"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "I file Markdown non sono supportati: usa invece i contenuti Markdown!"
|
msgstr "I file Markdown non sono supportati: usa invece i contenuti Markdown!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"deve essere fornito un file markdown o un contenuto markdown - si escludono "
|
"deve essere fornito un file markdown o un contenuto markdown - si escludono "
|
||||||
"a vicenda"
|
"a vicenda"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "identificatore interno del tag post"
|
msgstr "identificatore interno del tag post"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nome del tag"
|
msgstr "Nome del tag"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nome intuitivo per il tag del post"
|
msgstr "Nome intuitivo per il tag del post"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nome del tag"
|
msgstr "Nome del tag"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tag"
|
msgstr "Post tag"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tag dei post"
|
msgstr "Tag dei post"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "投稿タイトル"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "タイトル"
|
msgstr "タイトル"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "ポスト"
|
msgstr "ポスト"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "投稿"
|
msgstr "投稿"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"マークダウン・ファイルはサポートされていません - 代わりにマークダウン・コンテ"
|
"マークダウン・ファイルはサポートされていません - 代わりにマークダウン・コンテ"
|
||||||
"ンツを使用してください!"
|
"ンツを使用してください!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"マークダウン・ファイルまたはマークダウン・コンテンツを提供しなければならな"
|
"マークダウン・ファイルまたはマークダウン・コンテンツを提供しなければならな"
|
||||||
"い。"
|
"い。"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "投稿タグの内部タグ識別子"
|
msgstr "投稿タグの内部タグ識別子"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "タグ名"
|
msgstr "タグ名"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "投稿タグのユーザーフレンドリーな名前"
|
msgstr "投稿タグのユーザーフレンドリーな名前"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "タグ表示名"
|
msgstr "タグ表示名"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "投稿タグ"
|
msgstr "投稿タグ"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "投稿タグ"
|
msgstr "投稿タグ"
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
||||||
# This file is distributed under the same license as the EVIBES package.
|
# This file is distributed under the same license as the EVIBES package.
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -28,43 +28,43 @@ msgstr ""
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,43 +25,44 @@ msgstr "게시물 제목"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "제목"
|
msgstr "제목"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "게시물"
|
msgstr "게시물"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "게시물"
|
msgstr "게시물"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "마크다운 파일은 지원되지 않습니다 예 - 대신 마크다운 콘텐츠를 사용하세요!"
|
msgstr ""
|
||||||
|
"마크다운 파일은 지원되지 않습니다 예 - 대신 마크다운 콘텐츠를 사용하세요!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr "마크다운 파일 또는 마크다운 콘텐츠가 제공되어야 합니다."
|
msgstr "마크다운 파일 또는 마크다운 콘텐츠가 제공되어야 합니다."
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "게시물 태그의 내부 태그 식별자"
|
msgstr "게시물 태그의 내부 태그 식별자"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "태그 이름"
|
msgstr "태그 이름"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "게시물 태그의 사용자 친화적인 이름"
|
msgstr "게시물 태그의 사용자 친화적인 이름"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "태그 표시 이름"
|
msgstr "태그 표시 이름"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "게시물 태그"
|
msgstr "게시물 태그"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "게시물 태그"
|
msgstr "게시물 태그"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "Titel van de post"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Plaats"
|
msgstr "Plaats"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Berichten"
|
msgstr "Berichten"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Markdown-bestanden worden niet ondersteund - gebruik in plaats daarvan "
|
"Markdown-bestanden worden niet ondersteund - gebruik in plaats daarvan "
|
||||||
"markdown-inhoud!"
|
"markdown-inhoud!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"er moet een markdown-bestand of markdown-inhoud worden geleverd - wederzijds "
|
"er moet een markdown-bestand of markdown-inhoud worden geleverd - wederzijds "
|
||||||
"exclusief"
|
"exclusief"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "interne tagidentifier voor de posttag"
|
msgstr "interne tagidentifier voor de posttag"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tag naam"
|
msgstr "Tag naam"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Gebruiksvriendelijke naam voor de posttag"
|
msgstr "Gebruiksvriendelijke naam voor de posttag"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Tag weergavenaam"
|
msgstr "Tag weergavenaam"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tag"
|
msgstr "Post tag"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Post tags"
|
msgstr "Post tags"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,44 +25,44 @@ msgstr "Innleggets tittel"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Title"
|
msgstr "Title"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Innlegg"
|
msgstr "Innlegg"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "Markdown-filer støttes ikke - bruk markdown-innhold i stedet!"
|
msgstr "Markdown-filer støttes ikke - bruk markdown-innhold i stedet!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"en markdown-fil eller markdown-innhold må oppgis - gjensidig utelukkende"
|
"en markdown-fil eller markdown-innhold må oppgis - gjensidig utelukkende"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "intern tagg-identifikator for innleggstaggen"
|
msgstr "intern tagg-identifikator for innleggstaggen"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tagg navn"
|
msgstr "Tagg navn"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Brukervennlig navn for innleggstaggen"
|
msgstr "Brukervennlig navn for innleggstaggen"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Visningsnavn for taggen"
|
msgstr "Visningsnavn for taggen"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tag"
|
msgstr "Post tag"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tagger for innlegg"
|
msgstr "Tagger for innlegg"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,46 +25,46 @@ msgstr "Tytuł postu"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Tytuł"
|
msgstr "Tytuł"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Posty"
|
msgstr "Posty"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Pliki Markdown nie są obsługiwane - zamiast tego użyj zawartości Markdown!"
|
"Pliki Markdown nie są obsługiwane - zamiast tego użyj zawartości Markdown!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"należy dostarczyć plik markdown lub zawartość markdown - wzajemnie się "
|
"należy dostarczyć plik markdown lub zawartość markdown - wzajemnie się "
|
||||||
"wykluczające"
|
"wykluczające"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "wewnętrzny identyfikator tagu posta"
|
msgstr "wewnętrzny identyfikator tagu posta"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nazwa tagu"
|
msgstr "Nazwa tagu"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Przyjazna dla użytkownika nazwa tagu posta"
|
msgstr "Przyjazna dla użytkownika nazwa tagu posta"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Wyświetlana nazwa znacznika"
|
msgstr "Wyświetlana nazwa znacznika"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Tag posta"
|
msgstr "Tag posta"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tagi postów"
|
msgstr "Tagi postów"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,45 +25,45 @@ msgstr "Título da postagem"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Título"
|
msgstr "Título"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Postar"
|
msgstr "Postar"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Publicações"
|
msgstr "Publicações"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Os arquivos markdown não são suportados - use conteúdo markdown em vez disso!"
|
"Os arquivos markdown não são suportados - use conteúdo markdown em vez disso!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"um arquivo ou conteúdo de markdown deve ser fornecido - mutuamente exclusivo"
|
"um arquivo ou conteúdo de markdown deve ser fornecido - mutuamente exclusivo"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "identificador de tag interno para a tag de postagem"
|
msgstr "identificador de tag interno para a tag de postagem"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nome da etiqueta"
|
msgstr "Nome da etiqueta"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nome de fácil utilização para a tag de postagem"
|
msgstr "Nome de fácil utilização para a tag de postagem"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nome de exibição da tag"
|
msgstr "Nome de exibição da tag"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Etiqueta de postagem"
|
msgstr "Etiqueta de postagem"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Tags de postagem"
|
msgstr "Tags de postagem"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,46 +25,46 @@ msgstr "Titlul postului"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titlul"
|
msgstr "Titlul"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Mesaje"
|
msgstr "Mesaje"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Fișierele Markdown nu sunt acceptate - utilizați în schimb conținut Markdown!"
|
"Fișierele Markdown nu sunt acceptate - utilizați în schimb conținut Markdown!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"trebuie furnizat un fișier markdown sau conținut markdown - se exclud "
|
"trebuie furnizat un fișier markdown sau conținut markdown - se exclud "
|
||||||
"reciproc"
|
"reciproc"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "identificator intern de etichetă pentru eticheta postului"
|
msgstr "identificator intern de etichetă pentru eticheta postului"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Nume etichetă"
|
msgstr "Nume etichetă"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Nume ușor de utilizat pentru eticheta postului"
|
msgstr "Nume ușor de utilizat pentru eticheta postului"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Nume afișare etichetă"
|
msgstr "Nume afișare etichetă"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Etichetă post"
|
msgstr "Etichetă post"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Etichete poștale"
|
msgstr "Etichete poștale"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,47 @@ msgstr "Заголовок сообщения"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Название"
|
msgstr "Название"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Пост"
|
msgstr "Пост"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Посты"
|
msgstr "Посты"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Файлы в формате Markdown не поддерживаются - используйте вместо них "
|
"Файлы в формате Markdown не поддерживаются - используйте вместо них "
|
||||||
"содержимое в формате Markdown!"
|
"содержимое в формате Markdown!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"необходимо предоставить файл разметки или содержимое разметки - "
|
"необходимо предоставить файл разметки или содержимое разметки - "
|
||||||
"взаимоисключающие варианты"
|
"взаимоисключающие варианты"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "внутренний идентификатор тега для тега post"
|
msgstr "внутренний идентификатор тега для тега post"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Название тега"
|
msgstr "Название тега"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Удобное для пользователя название тега поста"
|
msgstr "Удобное для пользователя название тега поста"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Отображаемое имя тега"
|
msgstr "Отображаемое имя тега"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Тэг поста"
|
msgstr "Тэг поста"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Тэги постов"
|
msgstr "Тэги постов"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,45 +25,45 @@ msgstr "Inläggets titel"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Post"
|
msgstr "Post"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Inlägg"
|
msgstr "Inlägg"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "Markdown-filer stöds inte - använd markdown-innehåll istället!"
|
msgstr "Markdown-filer stöds inte - använd markdown-innehåll istället!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"en markdown-fil eller markdown-innehåll måste tillhandahållas - ömsesidigt "
|
"en markdown-fil eller markdown-innehåll måste tillhandahållas - ömsesidigt "
|
||||||
"uteslutande"
|
"uteslutande"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "intern taggidentifierare för inläggstaggen"
|
msgstr "intern taggidentifierare för inläggstaggen"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tagg namn"
|
msgstr "Tagg namn"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Användarvänligt namn för inläggstaggen"
|
msgstr "Användarvänligt namn för inläggstaggen"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Taggens visningsnamn"
|
msgstr "Taggens visningsnamn"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Post tagg"
|
msgstr "Post tagg"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Taggar för inlägg"
|
msgstr "Taggar för inlägg"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,45 +25,43 @@ msgstr "ชื่อโพสต์"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "ชื่อเรื่อง"
|
msgstr "ชื่อเรื่อง"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "โพสต์"
|
msgstr "โพสต์"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "โพสต์"
|
msgstr "โพสต์"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "ไฟล์มาร์กดาวน์ยังไม่รองรับในตอนนี้ - กรุณาใช้เนื้อหาแบบมาร์กดาวน์แทน!"
|
msgstr "ไฟล์มาร์กดาวน์ยังไม่รองรับในตอนนี้ - กรุณาใช้เนื้อหาแบบมาร์กดาวน์แทน!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr "ไฟล์มาร์กดาวน์หรือเนื้อหาแบบมาร์กดาวน์ต้องได้รับการจัดเตรียมไว้ - ไม่สามารถใช้ร่วมกันได้"
|
||||||
"ไฟล์มาร์กดาวน์หรือเนื้อหาแบบมาร์กดาวน์ต้องได้รับการจัดเตรียมไว้ - "
|
|
||||||
"ไม่สามารถใช้ร่วมกันได้"
|
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "ตัวระบุแท็กภายในสำหรับแท็กโพสต์"
|
msgstr "ตัวระบุแท็กภายในสำหรับแท็กโพสต์"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "ชื่อวัน"
|
msgstr "ชื่อวัน"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "ชื่อที่ใช้งานได้ง่ายสำหรับแท็กโพสต์"
|
msgstr "ชื่อที่ใช้งานได้ง่ายสำหรับแท็กโพสต์"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "แสดงชื่อแท็ก"
|
msgstr "แสดงชื่อแท็ก"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "โพสต์แท็ก"
|
msgstr "โพสต์แท็ก"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "ป้ายกำกับโพสต์"
|
msgstr "ป้ายกำกับโพสต์"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,47 +25,46 @@ msgstr "Gönderinin başlığı"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Başlık"
|
msgstr "Başlık"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Posta"
|
msgstr "Posta"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Mesajlar"
|
msgstr "Mesajlar"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Markdown dosyaları desteklenmiyor yer - bunun yerine markdown içeriği "
|
"Markdown dosyaları desteklenmiyor yer - bunun yerine markdown içeriği "
|
||||||
"kullanın!"
|
"kullanın!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"bir markdown dosyası veya markdown içeriği sağlanmalıdır - birbirini "
|
"bir markdown dosyası veya markdown içeriği sağlanmalıdır - birbirini dışlayan"
|
||||||
"dışlayan"
|
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "gönderi etiketi için dahili etiket tanımlayıcısı"
|
msgstr "gönderi etiketi için dahili etiket tanımlayıcısı"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Etiket adı"
|
msgstr "Etiket adı"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Gönderi etiketi için kullanıcı dostu ad"
|
msgstr "Gönderi etiketi için kullanıcı dostu ad"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Etiket görünen adı"
|
msgstr "Etiket görünen adı"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Mesaj etiketi"
|
msgstr "Mesaj etiketi"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Gönderi etiketleri"
|
msgstr "Gönderi etiketleri"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,46 +25,46 @@ msgstr "Tiêu đề bài đăng"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Tiêu đề"
|
msgstr "Tiêu đề"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "Bài đăng"
|
msgstr "Bài đăng"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "Bài đăng"
|
msgstr "Bài đăng"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Tệp Markdown hiện chưa được hỗ trợ - hãy sử dụng nội dung Markdown thay thế!"
|
"Tệp Markdown hiện chưa được hỗ trợ - hãy sử dụng nội dung Markdown thay thế!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Phải cung cấp tệp Markdown hoặc nội dung Markdown - hai tùy chọn này là "
|
"Phải cung cấp tệp Markdown hoặc nội dung Markdown - hai tùy chọn này là "
|
||||||
"tương phản nhau."
|
"tương phản nhau."
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "Mã định danh thẻ nội bộ cho thẻ bài viết"
|
msgstr "Mã định danh thẻ nội bộ cho thẻ bài viết"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "Tên ngày"
|
msgstr "Tên ngày"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "Tên thân thiện với người dùng cho thẻ bài viết"
|
msgstr "Tên thân thiện với người dùng cho thẻ bài viết"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "Hiển thị tên thẻ"
|
msgstr "Hiển thị tên thẻ"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "Thẻ bài viết"
|
msgstr "Thẻ bài viết"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "Thẻ bài viết"
|
msgstr "Thẻ bài viết"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 3.0.0\n"
|
"Project-Id-Version: EVIBES 3.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-19 15:04+0300\n"
|
"POT-Creation-Date: 2025-10-07 15:47+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
@ -25,43 +25,43 @@ msgstr "帖子标题"
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "标题"
|
msgstr "标题"
|
||||||
|
|
||||||
#: blog/models.py:83
|
#: blog/models.py:84
|
||||||
msgid "post"
|
msgid "post"
|
||||||
msgstr "职位"
|
msgstr "职位"
|
||||||
|
|
||||||
#: blog/models.py:84
|
#: blog/models.py:85
|
||||||
msgid "posts"
|
msgid "posts"
|
||||||
msgstr "职位"
|
msgstr "职位"
|
||||||
|
|
||||||
#: blog/models.py:88
|
#: blog/models.py:89
|
||||||
msgid "markdown files are not supported yet - use markdown content instead"
|
msgid "markdown files are not supported yet - use markdown content instead"
|
||||||
msgstr "不支持 Markdown 文件,请使用 Markdown 内容!"
|
msgstr "不支持 Markdown 文件,请使用 Markdown 内容!"
|
||||||
|
|
||||||
#: blog/models.py:90
|
#: blog/models.py:91
|
||||||
msgid ""
|
msgid ""
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
msgstr "必须提供标记符文件或标记符内容 - 相互排斥"
|
msgstr "必须提供标记符文件或标记符内容 - 相互排斥"
|
||||||
|
|
||||||
#: blog/models.py:122
|
#: blog/models.py:123
|
||||||
msgid "internal tag identifier for the post tag"
|
msgid "internal tag identifier for the post tag"
|
||||||
msgstr "职位标签的内部标签标识符"
|
msgstr "职位标签的内部标签标识符"
|
||||||
|
|
||||||
#: blog/models.py:123
|
#: blog/models.py:124
|
||||||
msgid "tag name"
|
msgid "tag name"
|
||||||
msgstr "标签名称"
|
msgstr "标签名称"
|
||||||
|
|
||||||
#: blog/models.py:127
|
#: blog/models.py:128
|
||||||
msgid "user-friendly name for the post tag"
|
msgid "user-friendly name for the post tag"
|
||||||
msgstr "方便用户使用的帖子标签名称"
|
msgstr "方便用户使用的帖子标签名称"
|
||||||
|
|
||||||
#: blog/models.py:128
|
#: blog/models.py:129
|
||||||
msgid "tag display name"
|
msgid "tag display name"
|
||||||
msgstr "标签显示名称"
|
msgstr "标签显示名称"
|
||||||
|
|
||||||
#: blog/models.py:136
|
#: blog/models.py:137
|
||||||
msgid "post tag"
|
msgid "post tag"
|
||||||
msgstr "职位标签"
|
msgstr "职位标签"
|
||||||
|
|
||||||
#: blog/models.py:137
|
#: blog/models.py:138
|
||||||
msgid "post tags"
|
msgid "post tags"
|
||||||
msgstr "帖子标签"
|
msgstr "帖子标签"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
# Generated by Django 5.2 on 2025-10-07 12:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("blog", "0005_post_content_fa_ir_post_content_he_il_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_ar_ar",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_cs_cz",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_da_dk",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_de_de",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_en_gb",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_en_us",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_es_es",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_fa_ir",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_fr_fr",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_he_il",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_hi_in",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_hr_hr",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_id_id",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_it_it",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_ja_jp",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_kk_kz",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_ko_kr",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_nl_nl",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_no_no",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_pl_pl",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_pt_br",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_ro_ro",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_ru_ru",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_sv_se",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_th_th",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_tr_tr",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_vi_vn",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="meta_description_zh_hans",
|
||||||
|
field=models.CharField(blank=True, max_length=150, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -75,6 +75,7 @@ class Post(NiceModel): # type: ignore [django-manager-missing]
|
||||||
file = FileField(upload_to="posts/", blank=True, null=True)
|
file = FileField(upload_to="posts/", blank=True, null=True)
|
||||||
slug = AutoSlugField(populate_from="title", allow_unicode=True, unique=True, editable=False)
|
slug = AutoSlugField(populate_from="title", allow_unicode=True, unique=True, editable=False)
|
||||||
tags = ManyToManyField(to="blog.PostTag", blank=True, related_name="posts")
|
tags = ManyToManyField(to="blog.PostTag", blank=True, related_name="posts")
|
||||||
|
meta_description = CharField(max_length=150, blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title} | {self.author.first_name} {self.author.last_name}"
|
return f"{self.title} | {self.author.first_name} {self.author.last_name}"
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ from blog.models import Post
|
||||||
|
|
||||||
@register(Post)
|
@register(Post)
|
||||||
class PostOptions(TranslationOptions):
|
class PostOptions(TranslationOptions):
|
||||||
fields = ("title", "content")
|
fields = ("title", "content", "meta_description")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
from typing import Collection
|
||||||
|
|
||||||
from django.db.models import BooleanField, Model, UUIDField
|
from django.db.models import BooleanField, Model, UUIDField
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -22,9 +23,19 @@ class NiceModel(Model):
|
||||||
created = CreationDateTimeField(_("created"), help_text=_("when the object first appeared on the database"))
|
created = CreationDateTimeField(_("created"), help_text=_("when the object first appeared on the database"))
|
||||||
modified = ModificationDateTimeField(_("modified"), help_text=_("when the object was last modified"))
|
modified = ModificationDateTimeField(_("modified"), help_text=_("when the object was last modified"))
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(
|
||||||
self.update_modified = kwargs.pop("update_modified", getattr(self, "update_modified", True))
|
self,
|
||||||
super().save(**kwargs)
|
*,
|
||||||
|
force_insert: bool = False,
|
||||||
|
force_update: bool = False,
|
||||||
|
using: str | None = None,
|
||||||
|
update_fields: Collection | None = None,
|
||||||
|
update_modified: bool = True,
|
||||||
|
) -> None:
|
||||||
|
self.update_modified = update_modified
|
||||||
|
return super().save(
|
||||||
|
force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from core.models import CustomerRelationshipManagementProvider
|
from core.models import CustomerRelationshipManagementProvider
|
||||||
|
|
||||||
|
|
||||||
def any_crm_integrations():
|
def any_crm_integrations() -> bool:
|
||||||
return CustomerRelationshipManagementProvider.objects.exists()
|
return CustomerRelationshipManagementProvider.objects.exists()
|
||||||
|
|
|
||||||
|
|
@ -89,15 +89,12 @@ class AmoCRM:
|
||||||
if type(order.attributes) is not dict:
|
if type(order.attributes) is not dict:
|
||||||
raise ValueError("order.attributes must be a dict")
|
raise ValueError("order.attributes must be a dict")
|
||||||
|
|
||||||
business_identificator = (
|
if order.user:
|
||||||
order.attributes.get("business_identificator")
|
if type(order.user.attributes) is not dict:
|
||||||
or order.attributes.get("businessIdentificator")
|
order.user.attributes = {}
|
||||||
or order.user.attributes.get("business_identificator")
|
order.user.save()
|
||||||
or order.user.attributes.get("businessIdentificator")
|
|
||||||
or ""
|
|
||||||
)
|
|
||||||
|
|
||||||
if not business_identificator:
|
if not order.business_identificator:
|
||||||
return (
|
return (
|
||||||
order.user.get_full_name()
|
order.user.get_full_name()
|
||||||
if order.user
|
if order.user
|
||||||
|
|
@ -109,7 +106,7 @@ class AmoCRM:
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"https://api-fns.ru/api/egr?req={business_identificator}&key={self.fns_api_key}", timeout=15
|
f"https://api-fns.ru/api/egr?req={order.business_identificator}&key={self.fns_api_key}", timeout=15
|
||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
body = r.json()
|
body = r.json()
|
||||||
|
|
@ -122,9 +119,9 @@ class AmoCRM:
|
||||||
ip = body.get("ИП")
|
ip = body.get("ИП")
|
||||||
|
|
||||||
if ul and not ip:
|
if ul and not ip:
|
||||||
return f"{ul.get('НаимСокрЮЛ')} | {business_identificator}"
|
return f"{ul.get('НаимСокрЮЛ')} | {order.business_identificator}"
|
||||||
if ip and not ul:
|
if ip and not ul:
|
||||||
return f"ИП {ip.get('ФИОПолн')} | {business_identificator}"
|
return f"ИП {ip.get('ФИОПолн')} | {order.business_identificator}"
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import re
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from blib2to3.pgen2.parse import Callable
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db.models import QuerySet
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -182,7 +185,7 @@ def process_query(
|
||||||
minimum_should_match=1,
|
minimum_should_match=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
def build_search(idxs, size):
|
def build_search(idxs: list[str], size: int) -> Search:
|
||||||
return (
|
return (
|
||||||
Search(index=idxs)
|
Search(index=idxs)
|
||||||
.query(query_base)
|
.query(query_base)
|
||||||
|
|
@ -221,9 +224,9 @@ def process_query(
|
||||||
search_products = build_search(["products"], size=44)
|
search_products = build_search(["products"], size=44)
|
||||||
resp_products = search_products.execute()
|
resp_products = search_products.execute()
|
||||||
|
|
||||||
results: dict = {"products": [], "categories": [], "brands": [], "posts": []}
|
results: dict[str, list[dict[str, Any]]] = {"products": [], "categories": [], "brands": [], "posts": []}
|
||||||
uuids_by_index: dict[str, list] = {"products": [], "categories": [], "brands": []}
|
uuids_by_index: dict[str, list[dict[str, Any]]] = {"products": [], "categories": [], "brands": []}
|
||||||
hit_cache: list = []
|
hit_cache: list[Any] = []
|
||||||
|
|
||||||
for h in (
|
for h in (
|
||||||
list(resp_cats.hits[:12] if resp_cats else [])
|
list(resp_cats.hits[:12] if resp_cats else [])
|
||||||
|
|
@ -325,10 +328,10 @@ def _lang_analyzer(lang_code: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
class ActiveOnlyMixin:
|
class ActiveOnlyMixin:
|
||||||
def get_queryset(self):
|
def get_queryset(self) -> QuerySet[Any]:
|
||||||
return super().get_queryset().filter(is_active=True)
|
return super().get_queryset().filter(is_active=True)
|
||||||
|
|
||||||
def should_index_object(self, obj):
|
def should_index_object(self, obj) -> bool:
|
||||||
return getattr(obj, "is_active", False)
|
return getattr(obj, "is_active", False)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -433,7 +436,7 @@ COMMON_ANALYSIS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def add_multilang_fields(cls):
|
def add_multilang_fields(cls) -> None:
|
||||||
for code, _lang in settings.LANGUAGES:
|
for code, _lang in settings.LANGUAGES:
|
||||||
lc = code.replace("-", "_").lower()
|
lc = code.replace("-", "_").lower()
|
||||||
name_field = f"name_{lc}"
|
name_field = f"name_{lc}"
|
||||||
|
|
@ -453,7 +456,7 @@ def add_multilang_fields(cls):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def make_prepare(attr):
|
def make_prepare(attr: str) -> Callable[[Any, Any], str]:
|
||||||
return lambda self, instance: getattr(instance, attr, "") or ""
|
return lambda self, instance: getattr(instance, attr, "") or ""
|
||||||
|
|
||||||
setattr(cls, f"prepare_{name_field}", make_prepare(name_field))
|
setattr(cls, f"prepare_{name_field}", make_prepare(name_field))
|
||||||
|
|
|
||||||
|
|
@ -277,19 +277,15 @@ class ProductFilter(FilterSet):
|
||||||
ordering_param = self.data.get("order_by", "")
|
ordering_param = self.data.get("order_by", "")
|
||||||
|
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
has_stock=Max(
|
has_stock=Case(
|
||||||
Case(
|
When(stocks__quantity__gt=0, then=Value(True)),
|
||||||
When(stocks__quantity__gt=0, then=Value(True)),
|
default=Value(False),
|
||||||
default=Value(False),
|
output_field=BooleanField(),
|
||||||
output_field=BooleanField(),
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
has_price=Max(
|
has_price=Case(
|
||||||
Case(
|
When(stocks__price__gt=0, then=Value(True)),
|
||||||
When(stocks__price__gt=0, then=Value(True)),
|
default=Value(False),
|
||||||
default=Value(False),
|
output_field=BooleanField(),
|
||||||
output_field=BooleanField(),
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
).annotate(
|
).annotate(
|
||||||
personal_orders_only=Case(
|
personal_orders_only=Case(
|
||||||
|
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@ from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
class RootDirectory:
|
class RootDirectory:
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.label = "root"
|
self.label = "root"
|
||||||
self.path = settings.BASE_DIR / "evibes"
|
self.path = settings.BASE_DIR / "evibes"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
@ -16,7 +17,7 @@ class Command(BaseCommand):
|
||||||
"in the translated_<lang> field created by django-modeltranslation."
|
"in the translated_<lang> field created by django-modeltranslation."
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t",
|
"-t",
|
||||||
"--target",
|
"--target",
|
||||||
|
|
@ -30,7 +31,7 @@ class Command(BaseCommand):
|
||||||
help="Modeltranslation language code to translate into, e.g. de-de, fr-fr, zh-hans",
|
help="Modeltranslation language code to translate into, e.g. de-de, fr-fr, zh-hans",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options) -> None:
|
||||||
target = options["target"]
|
target = options["target"]
|
||||||
lang = options["language"].lower()
|
lang = options["language"].lower()
|
||||||
|
|
||||||
|
|
|
||||||
453
core/models.py
453
core/models.py
|
|
@ -51,9 +51,9 @@ from core.errors import DisabledCommerceError, NotEnoughMoneyError
|
||||||
from core.managers import AddressManager, ProductManager
|
from core.managers import AddressManager, ProductManager
|
||||||
from core.utils import (
|
from core.utils import (
|
||||||
generate_human_readable_id,
|
generate_human_readable_id,
|
||||||
|
generate_human_readable_token,
|
||||||
get_product_uuid_as_path,
|
get_product_uuid_as_path,
|
||||||
get_random_code,
|
get_random_code,
|
||||||
generate_human_readable_token,
|
|
||||||
)
|
)
|
||||||
from core.utils.db import TweakedAutoSlugField, unicode_slugify_function
|
from core.utils.db import TweakedAutoSlugField, unicode_slugify_function
|
||||||
from core.utils.lists import FAILED_STATUSES
|
from core.utils.lists import FAILED_STATUSES
|
||||||
|
|
@ -66,7 +66,7 @@ logger = logging.getLogger("django")
|
||||||
|
|
||||||
|
|
||||||
class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a group of attributes, which can be hierarchical."
|
"Represents a group of attributes, which can be hierarchical."
|
||||||
" This class is used to manage and organize attribute groups."
|
" This class is used to manage and organize attribute groups."
|
||||||
" An attribute group can have a parent group, forming a hierarchical structure."
|
" An attribute group can have a parent group, forming a hierarchical structure."
|
||||||
|
|
@ -102,7 +102,7 @@ class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel):
|
||||||
|
|
||||||
|
|
||||||
class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a vendor entity capable of storing information about external vendors and their interaction requirements."
|
"Represents a vendor entity capable of storing information about external vendors and their interaction requirements."
|
||||||
" The Vendor class is used to define and manage information related to an external vendor."
|
" The Vendor class is used to define and manage information related to an external vendor."
|
||||||
" It stores the vendor's name, authentication details required for communication,"
|
" It stores the vendor's name, authentication details required for communication,"
|
||||||
|
|
@ -139,7 +139,15 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def save(self, **kwargs) -> None:
|
def save(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
force_insert=False,
|
||||||
|
force_update=False,
|
||||||
|
using=None,
|
||||||
|
update_fields=None,
|
||||||
|
update_modified: bool = True,
|
||||||
|
) -> None:
|
||||||
users = self.users.filter(is_active=True)
|
users = self.users.filter(is_active=True)
|
||||||
users = users.exclude(attributes__icontains="is_business")
|
users = users.exclude(attributes__icontains="is_business")
|
||||||
if users.count() > 0:
|
if users.count() > 0:
|
||||||
|
|
@ -148,7 +156,13 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [
|
||||||
user.attributes = {}
|
user.attributes = {}
|
||||||
user.attributes.update({"is_business": True})
|
user.attributes.update({"is_business": True})
|
||||||
user.save()
|
user.save()
|
||||||
return super().save(**kwargs)
|
return super().save(
|
||||||
|
force_insert=force_insert,
|
||||||
|
force_update=force_update,
|
||||||
|
using=using,
|
||||||
|
update_fields=update_fields,
|
||||||
|
update_modified=update_modified,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("vendor")
|
verbose_name = _("vendor")
|
||||||
|
|
@ -159,7 +173,7 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [
|
||||||
|
|
||||||
|
|
||||||
class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a product tag used for classifying or identifying products."
|
"Represents a product tag used for classifying or identifying products."
|
||||||
" The ProductTag class is designed to uniquely identify and classify products through a combination"
|
" The ProductTag class is designed to uniquely identify and classify products through a combination"
|
||||||
" of an internal tag identifier and a user-friendly display name."
|
" of an internal tag identifier and a user-friendly display name."
|
||||||
|
|
@ -191,7 +205,7 @@ class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): # type:
|
||||||
|
|
||||||
|
|
||||||
class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a category tag used for products."
|
"Represents a category tag used for products."
|
||||||
" This class models a category tag that can be used to associate and classify products."
|
" This class models a category tag that can be used to associate and classify products."
|
||||||
" It includes attributes for an internal tag identifier and a user-friendly display name."
|
" It includes attributes for an internal tag identifier and a user-friendly display name."
|
||||||
|
|
@ -222,7 +236,7 @@ class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): # typ
|
||||||
|
|
||||||
|
|
||||||
class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): # type: ignore [misc, django-manager-missing]
|
class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a category entity to organize and group related items in a hierarchical structure."
|
"Represents a category entity to organize and group related items in a hierarchical structure."
|
||||||
" Categories may have hierarchical relationships with other categories, supporting parent-child relationships."
|
" Categories may have hierarchical relationships with other categories, supporting parent-child relationships."
|
||||||
" The class includes fields for metadata and visual representation,"
|
" The class includes fields for metadata and visual representation,"
|
||||||
|
|
@ -314,24 +328,12 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): #
|
||||||
|
|
||||||
|
|
||||||
class Brand(ExportModelOperationsMixin("brand"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Brand(ExportModelOperationsMixin("brand"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a Brand object in the system.
|
"Represents a Brand object in the system. "
|
||||||
|
"This class handles information and attributes related to a brand, including its name, logos, "
|
||||||
This class handles information and attributes related to a brand, including its name, logos,
|
"description, associated categories, a unique slug, and priority order. "
|
||||||
description, associated categories, a unique slug, and priority order.
|
"It allows for the organization and representation of brand-related data within the application."
|
||||||
It allows for the organization and representation of brand-related data within the application.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): Indicates if the brand is visible publicly.
|
|
||||||
name (str): The name of the brand.
|
|
||||||
small_logo (ImageField): An optional small logo image file representing the brand.
|
|
||||||
big_logo (ImageField): An optional large logo image file representing the brand.
|
|
||||||
description (str): An optional textual description providing details about the brand.
|
|
||||||
categories (Category): Optional categories associated with this brand.
|
|
||||||
slug (str): A unique auto-generated slug used for SEO-friendly URLs.
|
|
||||||
priority (int): Specifies the priority ranking of the brand.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
@ -396,7 +398,7 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): # type: ignore [mi
|
||||||
|
|
||||||
|
|
||||||
class Stock(ExportModelOperationsMixin("stock"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Stock(ExportModelOperationsMixin("stock"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents the stock of a product managed in the system."
|
"Represents the stock of a product managed in the system."
|
||||||
" This class provides details about the relationship between vendors, products, and their stock information, "
|
" This class provides details about the relationship between vendors, products, and their stock information, "
|
||||||
"as well as inventory-related properties like price, purchase price, quantity, SKU, and digital assets."
|
"as well as inventory-related properties like price, purchase price, quantity, SKU, and digital assets."
|
||||||
|
|
@ -459,7 +461,7 @@ class Stock(ExportModelOperationsMixin("stock"), NiceModel): # type: ignore [mi
|
||||||
|
|
||||||
|
|
||||||
class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents a product with attributes such as category, brand, tags, digital status, name, description, part number, and slug."
|
"Represents a product with attributes such as category, brand, tags, digital status, name, description, part number, and slug."
|
||||||
" Provides related utility properties to retrieve ratings, feedback counts, price, quantity, and total orders."
|
" Provides related utility properties to retrieve ratings, feedback counts, price, quantity, and total orders."
|
||||||
" Designed for use in a system that handles e-commerce or inventory management."
|
" Designed for use in a system that handles e-commerce or inventory management."
|
||||||
|
|
@ -557,7 +559,7 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore
|
||||||
if rating is None:
|
if rating is None:
|
||||||
feedbacks = Feedback.objects.filter(order_product__product_id=self.pk)
|
feedbacks = Feedback.objects.filter(order_product__product_id=self.pk)
|
||||||
rating = feedbacks.aggregate(Avg("rating"))["rating__avg"] or 0
|
rating = feedbacks.aggregate(Avg("rating"))["rating__avg"] or 0
|
||||||
cache.set(cache_key, rating, 604800)
|
cache.set(cache_key, rating, 86400)
|
||||||
return round(rating, 2)
|
return round(rating, 2)
|
||||||
|
|
||||||
@rating.setter
|
@rating.setter
|
||||||
|
|
@ -601,9 +603,13 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore
|
||||||
def personal_orders_only(self) -> bool:
|
def personal_orders_only(self) -> bool:
|
||||||
return not (self.quantity > 0 and self.price > 0.0)
|
return not (self.quantity > 0 and self.price > 0.0)
|
||||||
|
|
||||||
|
@personal_orders_only.setter
|
||||||
|
def personal_orders_only(self, value):
|
||||||
|
self.__dict__["personal_orders_only"] = value
|
||||||
|
|
||||||
|
|
||||||
class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents an attribute in the system."
|
"Represents an attribute in the system."
|
||||||
" This class is used to define and manage attributes,"
|
" This class is used to define and manage attributes,"
|
||||||
" which are customizable pieces of data that can be associated with other entities."
|
" which are customizable pieces of data that can be associated with other entities."
|
||||||
|
|
@ -667,28 +673,11 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): # type: ig
|
||||||
|
|
||||||
|
|
||||||
class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a specific value for an attribute that is linked to a product.
|
"Represents a specific value for an attribute that is linked to a product. "
|
||||||
|
"It links the 'attribute' to a unique 'value', allowing "
|
||||||
This class serves the purpose of mapping a value to an attribute for a
|
"better organization and dynamic representation of product characteristics."
|
||||||
specific product. It links the 'attribute' to a unique 'value', allowing
|
)
|
||||||
better organization and dynamic representation of product characteristics.
|
|
||||||
It also defines whether the attribute value is public through the
|
|
||||||
'is_publicly_visible' attribute.
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
is_publicly_visible
|
|
||||||
Determines if the attribute value is visible publicly. Defaults to True.
|
|
||||||
attribute : core.Attribute
|
|
||||||
The 'Attribute' object this value is linked to. Foreign key relationship
|
|
||||||
with 'core.Attribute'.
|
|
||||||
product : core.Product
|
|
||||||
The specific 'Product' this attribute's value is associated with.
|
|
||||||
Foreign key relationship with 'core.Product'.
|
|
||||||
value
|
|
||||||
Holds the specific value for this attribute as a text field.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
@ -722,23 +711,13 @@ class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel):
|
||||||
|
|
||||||
|
|
||||||
class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a product image associated with a product in the system.
|
"Represents a product image associated with a product in the system. "
|
||||||
|
"This class is designed to manage images for products, including functionality "
|
||||||
This class is designed to manage images for products, including functionality
|
"for uploading image files, associating them with specific products, and "
|
||||||
for uploading image files, associating them with specific products, and
|
"determining their display order. It also includes an accessibility feature "
|
||||||
determining their display order. It also includes an accessibility feature
|
"with alternative text for the images."
|
||||||
with alternative text for the images.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): A flag indicating whether the image is
|
|
||||||
visible publicly.
|
|
||||||
alt (str): Alternative text for the image to support accessibility.
|
|
||||||
image (ImageField): The image file associated with the product.
|
|
||||||
priority (int): The display priority of the image. Images with lower
|
|
||||||
priority values are displayed first.
|
|
||||||
product (ForeignKey): The product associated with this image.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
@ -779,38 +758,14 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # t
|
||||||
|
|
||||||
|
|
||||||
class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a promotional campaign for products with a discount.
|
"Represents a promotional campaign for products with a discount. "
|
||||||
|
"This class is used to define and manage promotional campaigns that offer a "
|
||||||
This class is used to define and manage promotional campaigns that offer a
|
"percentage-based discount for products. The class includes attributes for "
|
||||||
percentage-based discount for products. The class includes attributes for
|
"setting the discount rate, providing details about the promotion, and linking "
|
||||||
setting the discount rate, providing details about the promotion, and linking
|
"it to the applicable products. It integrates with the product catalog to "
|
||||||
it to the applicable products. It integrates with the product catalog to
|
"determine the affected items in the campaign."
|
||||||
determine the affected items in the campaign.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible: A class-level attribute indicating whether the promotion
|
|
||||||
is publicly visible.
|
|
||||||
discount_percent: IntegerField. Specifies the percentage discount for the
|
|
||||||
selected products. Must be between 1 and 100 inclusive.
|
|
||||||
name: CharField. A unique name for the promotion, required for promoting
|
|
||||||
distinguishable campaigns. The maximum length is 256 characters.
|
|
||||||
description: TextField, optional. Provides a detailed description of the
|
|
||||||
promotion. Can be left blank or null.
|
|
||||||
products. Links the promotion to the products that are included
|
|
||||||
in its scope. Can be left blank.
|
|
||||||
|
|
||||||
Meta:
|
|
||||||
verbose_name: The singular name for the promotion in database and UI contexts.
|
|
||||||
verbose_name_plural: The pluralized name for multiple promotions in database and
|
|
||||||
UI contexts.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
__str__():
|
|
||||||
Returns a string representation of the promotion. If the name is
|
|
||||||
provided, it returns the name; otherwise, it returns the ID of the
|
|
||||||
promotion as a string.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
@ -849,15 +804,13 @@ class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): # type: ig
|
||||||
|
|
||||||
|
|
||||||
class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a user's wishlist for storing and managing desired products.
|
"Represents a user's wishlist for storing and managing desired products. "
|
||||||
|
"The class provides functionality to manage a collection of products, "
|
||||||
The Wishlist class provides functionality to manage a collection of products
|
"supporting operations such as adding and removing products, "
|
||||||
that a user wishes to save. It supports operations such as adding products,
|
"as well as supporting operations for adding and removing multiple "
|
||||||
removing products, adding multiple products in bulk, and removing multiple
|
"products at once."
|
||||||
products in bulk. The wishlist is associated with a specific user and is
|
)
|
||||||
stored with optional public visibility status.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
|
|
@ -922,25 +875,13 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): # type: igno
|
||||||
|
|
||||||
|
|
||||||
class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Model representing a documentary record tied to a product.
|
"Represents a documentary record tied to a product. "
|
||||||
|
"This class is used to store information about documentaries related to specific "
|
||||||
This class is used to store information about documentaries related to specific
|
"products, including file uploads and their metadata. It contains methods and "
|
||||||
products, including file uploads and their metadata. It contains methods and
|
"properties to handle the file type and storage path for the documentary files. "
|
||||||
properties to handle the file type and storage path for the documentary files.
|
"It extends functionality from specific mixins and provides additional custom features."
|
||||||
It extends functionality from specific mixins and provides additional custom
|
)
|
||||||
features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible: A boolean indicating if the documentary is
|
|
||||||
publicly visible.
|
|
||||||
product linking the documentary to a product.
|
|
||||||
document: FileField used to store the file associated with the documentary.
|
|
||||||
|
|
||||||
Meta:
|
|
||||||
verbose_name: Singular name for the documentary model.
|
|
||||||
verbose_name_plural: Plural name for the documentary model.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
@ -963,42 +904,16 @@ class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): #
|
||||||
|
|
||||||
|
|
||||||
class Address(ExportModelOperationsMixin("address"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Address(ExportModelOperationsMixin("address"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents an address entity that includes location details and associations with
|
"Represents an address entity that includes location details and associations with a user. "
|
||||||
a user. Provides functionality for geographic and address data storage, as well
|
"Provides functionality for geographic and address data storage, as well "
|
||||||
as integration with geocoding services.
|
"as integration with geocoding services. "
|
||||||
|
"This class is designed to store detailed address information including components "
|
||||||
This class is designed to store detailed address information including components
|
"like street, city, region, country, and geolocation (longitude and latitude). "
|
||||||
like street, city, region, country, and geolocation (longitude and latitude).
|
"It supports integration with geocoding APIs, enabling the storage of raw API "
|
||||||
|
"responses for further processing or inspection. The class also allows associating "
|
||||||
It supports integration with geocoding APIs, enabling the storage of raw API
|
"an address with a user, facilitating personalized data handling."
|
||||||
responses for further processing or inspection. The class also allows associating
|
)
|
||||||
an address with a user, facilitating personalized data handling.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): Indicates whether the address is visible publicly.
|
|
||||||
address_line (str): A general address line containing information about the
|
|
||||||
customer's location. Optional.
|
|
||||||
street (str): The street name or number in the address. Optional.
|
|
||||||
district (str): The district related to the address. Optional.
|
|
||||||
city (str): The name of the city where the address is located. Optional.
|
|
||||||
region (str): The name of the region associated with the address. Optional.
|
|
||||||
postal_code (str): The postal code corresponding to the address. Optional.
|
|
||||||
country (str): The country where the address resides. Optional.
|
|
||||||
location (PointField): A geolocation represented as (longitude, latitude).
|
|
||||||
Allows geospatial searches. Optional.
|
|
||||||
raw_data (dict): The full JSON response directly from the geocoding service,
|
|
||||||
containing detailed information about the address. Optional.
|
|
||||||
api_response (dict): Stores a processed version or subset of the JSON
|
|
||||||
response from the geocoding service. Optional.
|
|
||||||
user (ForeignKey): Reference to a User entity who owns this address. Optional.
|
|
||||||
|
|
||||||
Meta:
|
|
||||||
verbose_name (str): Human-readable singular name for the address.
|
|
||||||
verbose_name_plural (str): Human-readable plural name for addresses.
|
|
||||||
indexes (list): Database indexes defined for improving query performance
|
|
||||||
on specific fields like 'location'.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
|
|
@ -1048,33 +963,14 @@ class Address(ExportModelOperationsMixin("address"), NiceModel): # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a promotional code that can be used for discounts, managing its validity,
|
"Represents a promotional code that can be used for discounts, managing its validity, "
|
||||||
type of discount, and application.
|
"type of discount, and application. "
|
||||||
|
"The PromoCode class stores details about a promotional code, including its unique "
|
||||||
The PromoCode class stores details about a promotional code, including its unique
|
"identifier, discount properties (amount or percentage), validity period, associated "
|
||||||
identifier, discount properties (amount or percentage), validity period, associated
|
"user (if any), and status of its usage. It includes functionality to validate and "
|
||||||
user (if any), and status of its usage. It includes functionality to validate and
|
"apply the promo code to an order while ensuring constraints are met."
|
||||||
apply the promo code to an order while ensuring constraints are met.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
code (str): The unique identifier for the promo code.
|
|
||||||
discount_amount (Decimal): The fixed discount amount applied, if defined.
|
|
||||||
discount_percent (int): The percentage discount applied, if defined.
|
|
||||||
end_time (datetime): The expiration timestamp of the promo code.
|
|
||||||
start_time (datetime): The timestamp from when the promo code is valid.
|
|
||||||
used_on (datetime): The timestamp when the promo code was used (if applicable).
|
|
||||||
user (ForeignKey): The user associated with the promo code, if any.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
save(**kwargs): Ensures only one type of discount (amount or percent) is defined.
|
|
||||||
__str__(): Returns the promo code identifier as its string representation.
|
|
||||||
use(order): Applies the promo code to the given order and calculates the final price.
|
|
||||||
|
|
||||||
Meta:
|
|
||||||
verbose_name: Display name for the promo code model.
|
|
||||||
verbose_name_plural: Plural display name for the promo code model.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
|
|
@ -1132,14 +1028,28 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): # type: ig
|
||||||
verbose_name = _("promo code")
|
verbose_name = _("promo code")
|
||||||
verbose_name_plural = _("promo codes")
|
verbose_name_plural = _("promo codes")
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(
|
||||||
|
self,
|
||||||
|
*args,
|
||||||
|
force_insert=False,
|
||||||
|
force_update=False,
|
||||||
|
using=None,
|
||||||
|
update_fields=None,
|
||||||
|
update_modified: bool = True,
|
||||||
|
) -> None:
|
||||||
if (self.discount_amount is not None and self.discount_percent is not None) or (
|
if (self.discount_amount is not None and self.discount_percent is not None) or (
|
||||||
self.discount_amount is None and self.discount_percent is None
|
self.discount_amount is None and self.discount_percent is None
|
||||||
):
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_("only one type of discount should be defined (amount or percent), but not both or neither.")
|
_("only one type of discount should be defined (amount or percent), but not both or neither.")
|
||||||
)
|
)
|
||||||
super().save(**kwargs)
|
return super().save(
|
||||||
|
force_insert=force_insert,
|
||||||
|
force_update=force_update,
|
||||||
|
using=using,
|
||||||
|
update_fields=update_fields,
|
||||||
|
update_modified=update_modified,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.code
|
return self.code
|
||||||
|
|
@ -1176,7 +1086,7 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): # type: ig
|
||||||
|
|
||||||
|
|
||||||
class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
__doc__ = _(
|
__doc__ = _( # type: ignore
|
||||||
"Represents an order placed by a user."
|
"Represents an order placed by a user."
|
||||||
" This class models an order within the application,"
|
" This class models an order within the application,"
|
||||||
" including its various attributes such as billing and shipping information,"
|
" including its various attributes such as billing and shipping information,"
|
||||||
|
|
@ -1270,21 +1180,40 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
|
||||||
self.attributes = {}
|
self.attributes = {}
|
||||||
self.save()
|
self.save()
|
||||||
return False
|
return False
|
||||||
|
if self.user:
|
||||||
|
if type(self.user.attributes) is not dict:
|
||||||
|
self.user.attributes = {}
|
||||||
|
self.user.save()
|
||||||
|
return False
|
||||||
with suppress(Exception):
|
with suppress(Exception):
|
||||||
return (self.attributes.get("is_business", False) if self.attributes else False) or (
|
return (self.attributes.get("is_business", False) if self.attributes else False) or (
|
||||||
(self.user.attributes.get("is_business", False) and self.user.attributes.get("business_identificator"))
|
(self.user.attributes.get("is_business", False) and self.user.attributes.get("business_identificator")) # type: ignore [union-attr]
|
||||||
if self.user
|
if self.user
|
||||||
else False
|
else False
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def save(self, **kwargs) -> Self:
|
def save(
|
||||||
|
self,
|
||||||
|
*args,
|
||||||
|
force_insert=False,
|
||||||
|
force_update=False,
|
||||||
|
using=None,
|
||||||
|
update_fields=None,
|
||||||
|
update_modified: bool = True,
|
||||||
|
) -> None:
|
||||||
pending_orders = 0
|
pending_orders = 0
|
||||||
if self.user:
|
if self.user:
|
||||||
pending_orders = self.user.orders.filter(status="PENDING").count()
|
pending_orders = self.user.orders.filter(status="PENDING").count()
|
||||||
if self.status == "PENDING" and pending_orders > 1:
|
if self.status == "PENDING" and pending_orders > 1:
|
||||||
raise ValueError(_("a user must have only one pending order at a time"))
|
raise ValueError(_("a user must have only one pending order at a time"))
|
||||||
return super().save(**kwargs)
|
return super().save(
|
||||||
|
force_insert=force_insert,
|
||||||
|
force_update=force_update,
|
||||||
|
using=using,
|
||||||
|
update_fields=update_fields,
|
||||||
|
update_modified=update_modified,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_price(self) -> float:
|
def total_price(self) -> float:
|
||||||
|
|
@ -1431,8 +1360,8 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
|
||||||
shipping_address = billing_address
|
shipping_address = billing_address
|
||||||
|
|
||||||
else:
|
else:
|
||||||
billing_address = Address.objects.get(uuid=billing_address_uuid)
|
billing_address = Address.objects.get(uuid=str(billing_address_uuid))
|
||||||
shipping_address = Address.objects.get(uuid=shipping_address_uuid)
|
shipping_address = Address.objects.get(uuid=str(shipping_address_uuid))
|
||||||
|
|
||||||
self.billing_address = billing_address
|
self.billing_address = billing_address
|
||||||
self.shipping_address = shipping_address
|
self.shipping_address = shipping_address
|
||||||
|
|
@ -1645,30 +1574,29 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def business_identificator(self) -> str | None:
|
||||||
|
if self.attributes:
|
||||||
|
return self.attributes.get("business_identificator") or self.attributes.get("businessIdentificator")
|
||||||
|
if self.user:
|
||||||
|
if self.user.attributes:
|
||||||
|
return self.user.attributes.get("business_identificator") or self.user.attributes.get(
|
||||||
|
"businessIdentificator"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents a product associated with an order.
|
"Represents products associated with orders and their attributes. "
|
||||||
|
"The OrderProduct model maintains information about a product that is part of an order, "
|
||||||
The OrderProduct model maintains information about a product that is part of an order,
|
"including details such as purchase price, quantity, product attributes, and status. It "
|
||||||
including details such as purchase price, quantity, product attributes, and status. It
|
"manages notifications for the user and administrators and handles operations such as "
|
||||||
manages notifications for the user and administrators and handles operations such as
|
"returning the product balance or adding feedback. This model also provides methods and "
|
||||||
returning the product balance or adding feedback. This model also provides methods and
|
"properties that support business logic, such as calculating the total price or generating "
|
||||||
properties that support business logic, such as calculating the total price or generating
|
"a download URL for digital products. The model integrates with the Order and Product models "
|
||||||
a download URL for digital products. The model integrates with the Order and Product models
|
"and stores a reference to them."
|
||||||
and stores a reference to them.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): Indicates whether this model is visible publicly.
|
|
||||||
buy_price (float): The price paid by the customer for this product at purchase time.
|
|
||||||
comments (str): Internal comments entered by admins regarding this ordered product.
|
|
||||||
notifications (dict): JSON structure containing notifications relevant to the product.
|
|
||||||
attributes (dict): JSON representation of the product's attributes as part of the order.
|
|
||||||
order (Order): Reference to the parent order that contains this product.
|
|
||||||
product (Product): Reference to the specific product associated with the order line.
|
|
||||||
quantity (int): Represents the quantity of this product ordered.
|
|
||||||
status (str): The current status of the product in the order.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
|
|
@ -1780,9 +1708,9 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): # t
|
||||||
def download_url(self: Self) -> str:
|
def download_url(self: Self) -> str:
|
||||||
if self.product and self.product.stocks:
|
if self.product and self.product.stocks:
|
||||||
if self.product.is_digital and self.product.stocks.first().digital_asset: # type: ignore [union-attr]
|
if self.product.is_digital and self.product.stocks.first().digital_asset: # type: ignore [union-attr]
|
||||||
try:
|
if hasattr(self, "download"):
|
||||||
return self.download.url
|
return self.download.url
|
||||||
except self.download.RelatedObjectDoesNotExist:
|
else:
|
||||||
return DigitalAssetDownload.objects.create(order_product=self).url
|
return DigitalAssetDownload.objects.create(order_product=self).url
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
@ -1809,7 +1737,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): # t
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class CustomerRelationshipManagementProvider(ExportModelOperationsMixin("crm_provider"), NiceModel):
|
class CustomerRelationshipManagementProvider(ExportModelOperationsMixin("crm_provider"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
name = CharField(max_length=128, unique=True, verbose_name=_("name"))
|
name = CharField(max_length=128, unique=True, verbose_name=_("name"))
|
||||||
integration_url = URLField(blank=True, null=True, help_text=_("URL of the integration"))
|
integration_url = URLField(blank=True, null=True, help_text=_("URL of the integration"))
|
||||||
authentication = JSONField(blank=True, null=True, help_text=_("authentication credentials"))
|
authentication = JSONField(blank=True, null=True, help_text=_("authentication credentials"))
|
||||||
|
|
@ -1820,14 +1748,28 @@ class CustomerRelationshipManagementProvider(ExportModelOperationsMixin("crm_pro
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(
|
||||||
|
self,
|
||||||
|
*args,
|
||||||
|
force_insert=False,
|
||||||
|
force_update=False,
|
||||||
|
using=None,
|
||||||
|
update_fields=None,
|
||||||
|
update_modified: bool = True,
|
||||||
|
) -> None:
|
||||||
if self.default:
|
if self.default:
|
||||||
qs = type(self).objects.all()
|
qs = type(self).objects.all()
|
||||||
if self.pk:
|
if self.pk:
|
||||||
qs = qs.exclude(pk=self.pk)
|
qs = qs.exclude(pk=self.pk)
|
||||||
if qs.filter(default=True).exists():
|
if qs.filter(default=True).exists():
|
||||||
raise ValueError(_("you can only have one default CRM provider"))
|
raise ValueError(_("you can only have one default CRM provider"))
|
||||||
super().save(**kwargs)
|
super().save(
|
||||||
|
force_insert=force_insert,
|
||||||
|
force_update=force_update,
|
||||||
|
using=using,
|
||||||
|
update_fields=update_fields,
|
||||||
|
update_modified=update_modified,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("CRM")
|
verbose_name = _("CRM")
|
||||||
|
|
@ -1848,29 +1790,14 @@ class OrderCrmLink(ExportModelOperationsMixin("order_crm_link"), NiceModel): #
|
||||||
|
|
||||||
|
|
||||||
class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Represents the downloading functionality for digital assets associated
|
"Represents the downloading functionality for digital assets associated with orders. "
|
||||||
with orders.
|
"The DigitalAssetDownload class provides the ability to manage and access "
|
||||||
|
"downloads related to order products. It maintains information about the "
|
||||||
The DigitalAssetDownload class provides the ability to manage and access
|
"associated order product, the number of downloads, and whether the asset "
|
||||||
downloads related to order products. It maintains information about the
|
"is publicly visible. It includes a method to generate a URL for downloading "
|
||||||
associated order product, the number of downloads, and whether the asset
|
"the asset when the associated order is in a completed status."
|
||||||
is publicly visible. It includes a method to generate a URL for downloading
|
)
|
||||||
the asset when the associated order is in a completed status.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): Indicates whether the digital asset is
|
|
||||||
publicly visible. Always set to False for this class.
|
|
||||||
order_product (OneToOneField): Reference to the associated order product.
|
|
||||||
It has a one-to-one relationship with the OrderProduct model, and
|
|
||||||
deleting the OrderProduct will delete the associated download.
|
|
||||||
num_downloads (int): Indicates the number of times the digital asset
|
|
||||||
has been downloaded.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
url: Property to generate the download URL for the digital asset
|
|
||||||
if the associated order is in a finished status.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
|
|
@ -1886,31 +1813,19 @@ class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceMo
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
if self.order_product.status != "FINISHED":
|
|
||||||
raise ValueError(_("you can not download a digital asset for a non-finished order"))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): # type: ignore [misc, django-manager-missing]
|
class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): # type: ignore [misc, django-manager-missing]
|
||||||
"""
|
__doc__ = _( # type: ignore
|
||||||
Manages user feedback for products.
|
"Manages user feedback for products. "
|
||||||
|
"This class is designed to capture and store user feedback for specific products "
|
||||||
This class is designed to capture and store user feedback for specific products
|
"that they have purchased. It contains attributes to store user comments, "
|
||||||
that they have purchased. It contains attributes to store user comments,
|
"a reference to the related product in the order, and a user-assigned rating. The "
|
||||||
a reference to the related product in the order, and a user-assigned rating. The
|
"class uses database fields to effectively model and manage feedback data."
|
||||||
class uses database fields to effectively model and manage feedback data.
|
)
|
||||||
|
|
||||||
Attributes:
|
|
||||||
is_publicly_visible (bool): Indicates whether the feedback is visible to the public.
|
|
||||||
comment (str): User-provided comments about their experience with the product.
|
|
||||||
order_product (OrderProduct): Reference to the specific product in an order that this
|
|
||||||
feedback is about.
|
|
||||||
rating (float): User-assigned rating for the product, validated to be within the range
|
|
||||||
of 0 to 10.
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,15 +84,18 @@ def process_order_changes(instance, created, **_kwargs):
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
human_readable_id = generate_human_readable_id()
|
human_readable_id = generate_human_readable_id()
|
||||||
while True:
|
while True:
|
||||||
if Order.objects.filter(human_readable_id=human_readable_id).exists():
|
try:
|
||||||
human_readable_id = generate_human_readable_id()
|
if Order.objects.filter(human_readable_id=human_readable_id).exists():
|
||||||
|
human_readable_id = generate_human_readable_id()
|
||||||
|
continue
|
||||||
|
Order.objects.create(
|
||||||
|
user=instance,
|
||||||
|
status="PENDING",
|
||||||
|
human_readable_id=human_readable_id,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except IntegrityError:
|
||||||
continue
|
continue
|
||||||
Order.objects.create(
|
|
||||||
user=instance,
|
|
||||||
status="PENDING",
|
|
||||||
human_readable_id=human_readable_id,
|
|
||||||
)
|
|
||||||
break
|
|
||||||
|
|
||||||
if instance.status in ["CREATED", "PAYMENT"]:
|
if instance.status in ["CREATED", "PAYMENT"]:
|
||||||
if not instance.is_whole_digital:
|
if not instance.is_whole_digital:
|
||||||
|
|
@ -110,12 +113,15 @@ def process_order_changes(instance, created, **_kwargs):
|
||||||
|
|
||||||
if has_file:
|
if has_file:
|
||||||
order_product.status = "FINISHED"
|
order_product.status = "FINISHED"
|
||||||
download = DigitalAssetDownload.objects.create(order_product=order_product)
|
if not order_product.download:
|
||||||
order_product.download = download
|
DigitalAssetDownload.objects.create(order_product=order_product)
|
||||||
order_product.save()
|
order_product.order.user.payments_balance.amount -= order_product.buy_price
|
||||||
order_product.order.user.payments_balance.amount -= order_product.buy_price
|
order_product.order.user.payments_balance.save()
|
||||||
order_product.order.user.payments_balance.save()
|
order_product.save()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
order_product.save()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
vendor_name = (
|
vendor_name = (
|
||||||
order_product.product.stocks.filter(price=order_product.buy_price).first().vendor.name.lower()
|
order_product.product.stocks.filter(price=order_product.buy_price).first().vendor.name.lower()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from django.core.cache import cache
|
||||||
|
|
||||||
from core.models import Product, Promotion
|
from core.models import Product, Promotion
|
||||||
from core.utils.caching import set_default_cache
|
from core.utils.caching import set_default_cache
|
||||||
from core.vendors import delete_stale, VendorInactiveError
|
from core.vendors import VendorInactiveError, delete_stale
|
||||||
from evibes.settings import MEDIA_ROOT
|
from evibes.settings import MEDIA_ROOT
|
||||||
|
|
||||||
logger = get_task_logger(__name__)
|
logger = get_task_logger(__name__)
|
||||||
|
|
@ -38,7 +38,7 @@ def update_products_task() -> tuple[bool, str]:
|
||||||
|
|
||||||
if not update_products_task_running:
|
if not update_products_task_running:
|
||||||
cache.set("update_products_task_running", True, 86400)
|
cache.set("update_products_task_running", True, 86400)
|
||||||
vendors_classes = []
|
vendors_classes: list = []
|
||||||
|
|
||||||
for vendor_class in vendors_classes:
|
for vendor_class in vendors_classes:
|
||||||
vendor = vendor_class()
|
vendor = vendor_class()
|
||||||
|
|
@ -69,7 +69,7 @@ def update_orderproducts_task() -> tuple[bool, str]:
|
||||||
message confirming the successful execution of the task.
|
message confirming the successful execution of the task.
|
||||||
:rtype: Tuple[bool, str]
|
:rtype: Tuple[bool, str]
|
||||||
"""
|
"""
|
||||||
vendors_classes = []
|
vendors_classes: list = []
|
||||||
|
|
||||||
for vendor_class in vendors_classes:
|
for vendor_class in vendors_classes:
|
||||||
vendor = vendor_class()
|
vendor = vendor_class()
|
||||||
|
|
@ -95,7 +95,7 @@ def set_default_caches_task() -> tuple[bool, str]:
|
||||||
|
|
||||||
|
|
||||||
@shared_task(queue="default")
|
@shared_task(queue="default")
|
||||||
def remove_stale_product_images() -> tuple[bool, str] | None:
|
def remove_stale_product_images() -> tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Removes stale product images from the products directory by identifying directories
|
Removes stale product images from the products directory by identifying directories
|
||||||
whose names do not match any UUIDs currently present in the database.
|
whose names do not match any UUIDs currently present in the database.
|
||||||
|
|
@ -114,7 +114,7 @@ def remove_stale_product_images() -> tuple[bool, str] | None:
|
||||||
products_dir = os.path.join(MEDIA_ROOT, "products")
|
products_dir = os.path.join(MEDIA_ROOT, "products")
|
||||||
if not os.path.isdir(products_dir):
|
if not os.path.isdir(products_dir):
|
||||||
logger.info("The products directory does not exist: %s", products_dir)
|
logger.info("The products directory does not exist: %s", products_dir)
|
||||||
return
|
return True, "The products directory does not exist."
|
||||||
|
|
||||||
# Load all current product UUIDs into a set.
|
# Load all current product UUIDs into a set.
|
||||||
# This query returns all product UUIDs (as strings or UUID objects).
|
# This query returns all product UUIDs (as strings or UUID objects).
|
||||||
|
|
@ -139,6 +139,7 @@ def remove_stale_product_images() -> tuple[bool, str] | None:
|
||||||
logger.info("Removed stale product images directory: %s", entry_path)
|
logger.info("Removed stale product images directory: %s", entry_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error removing directory %s: %s", entry_path, e)
|
logger.error("Error removing directory %s: %s", entry_path, e)
|
||||||
|
return True, "Successfully removed stale product images."
|
||||||
|
|
||||||
|
|
||||||
@shared_task(queue="default")
|
@shared_task(queue="default")
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button type="button" class="add-row-button" data-table-id="json-fields-{{ widget.attrs.id }}">
|
<button type="button" class="add-row-button" data-table-id="json-fields-{{ widget.attrs.id }}">
|
||||||
Add Row
|
{% blocktrans %}Add Row{% endblocktrans %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from evibes.settings import DEBUG, EXPOSABLE_KEYS, LANGUAGE_CODE
|
||||||
logger = logging.getLogger("django")
|
logger = logging.getLogger("django")
|
||||||
|
|
||||||
|
|
||||||
def graphene_current_lang():
|
def graphene_current_lang() -> str:
|
||||||
"""
|
"""
|
||||||
Determines the currently active language code.
|
Determines the currently active language code.
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ def graphene_abs(request, path_or_url: str) -> str:
|
||||||
Returns:
|
Returns:
|
||||||
str: The absolute URI corresponding to the provided path or URL.
|
str: The absolute URI corresponding to the provided path or URL.
|
||||||
"""
|
"""
|
||||||
return request.build_absolute_uri(path_or_url)
|
return str(request.build_absolute_uri(path_or_url))
|
||||||
|
|
||||||
|
|
||||||
def get_random_code() -> str:
|
def get_random_code() -> str:
|
||||||
|
|
@ -64,40 +64,10 @@ def get_random_code() -> str:
|
||||||
|
|
||||||
|
|
||||||
def get_product_uuid_as_path(instance, filename: str = "") -> str:
|
def get_product_uuid_as_path(instance, filename: str = "") -> str:
|
||||||
"""
|
|
||||||
Generates a file path for a product using its UUID.
|
|
||||||
|
|
||||||
This function constructs a standardized file path where an uploaded file
|
|
||||||
is saved for a product. The path includes a `products` directory, followed
|
|
||||||
by the product's UUID, and concludes with the original filename. It can be
|
|
||||||
utilized in file storage applications to ensure unique and organized file
|
|
||||||
storage based on the product's identity.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
instance: The object instance that contains a reference to the product.
|
|
||||||
filename: str, optional. The name of the file being uploaded. Default is an
|
|
||||||
empty string.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: A string that represents the constructed file path.
|
|
||||||
"""
|
|
||||||
return "products" + "/" + str(instance.product.uuid) + "/" + filename
|
return "products" + "/" + str(instance.product.uuid) + "/" + filename
|
||||||
|
|
||||||
|
|
||||||
def get_brand_name_as_path(instance, filename: str = "") -> str:
|
def get_brand_name_as_path(instance, filename: str = "") -> str:
|
||||||
"""
|
|
||||||
Generates a file path for a brand based on its name and the provided filename.
|
|
||||||
|
|
||||||
This function constructs a unique file path within the 'brands/' directory using
|
|
||||||
the name of the given instance and appends the supplied filename.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
instance: An object containing a 'name' attribute.
|
|
||||||
filename: str, optional. The name of the file to be appended to the path.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: A string representing the constructed file path.
|
|
||||||
"""
|
|
||||||
return "brands/" + str(instance.name) + "/" + filename
|
return "brands/" + str(instance.name) + "/" + filename
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -111,9 +81,6 @@ def atomic_if_not_debug():
|
||||||
database transaction, preventing partial updates to the database in case of
|
database transaction, preventing partial updates to the database in case of
|
||||||
an exception. If the DEBUG setting is enabled, no transaction is enforced,
|
an exception. If the DEBUG setting is enabled, no transaction is enforced,
|
||||||
allowing for easier debugging.
|
allowing for easier debugging.
|
||||||
|
|
||||||
Yields:
|
|
||||||
None: This context manager does not return any values.
|
|
||||||
"""
|
"""
|
||||||
if not DEBUG:
|
if not DEBUG:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
|
@ -123,18 +90,6 @@ def atomic_if_not_debug():
|
||||||
|
|
||||||
|
|
||||||
def is_url_safe(url: str) -> bool:
|
def is_url_safe(url: str) -> bool:
|
||||||
"""
|
|
||||||
Determines if a given URL starts with "https://" indicating it is a secure URL.
|
|
||||||
|
|
||||||
This function checks if the provided URL adheres to secure HTTPS protocol.
|
|
||||||
It uses a regular expression to validate the URL prefix.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
url (str): The URL string to validate.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if the URL starts with "https://", False otherwise.
|
|
||||||
"""
|
|
||||||
return bool(re.match(r"^https://", url, re.IGNORECASE))
|
return bool(re.match(r"^https://", url, re.IGNORECASE))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -146,14 +101,6 @@ def format_attributes(attributes: str | None = None) -> dict:
|
||||||
formatted as `key=value` pairs separated by commas, and converts it into a
|
formatted as `key=value` pairs separated by commas, and converts it into a
|
||||||
dictionary. It returns an empty dictionary if the input is `None` or invalid.
|
dictionary. It returns an empty dictionary if the input is `None` or invalid.
|
||||||
Invalid key-value pairs within the input string are skipped.
|
Invalid key-value pairs within the input string are skipped.
|
||||||
|
|
||||||
Parameters:
|
|
||||||
attributes (str | None): A comma-separated string of key-value pairs in the
|
|
||||||
format `key=value`, or None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: A dictionary where keys are the attribute names and values are their
|
|
||||||
corresponding values.
|
|
||||||
"""
|
"""
|
||||||
if not attributes:
|
if not attributes:
|
||||||
return {}
|
return {}
|
||||||
|
|
@ -182,9 +129,6 @@ def get_project_parameters() -> dict:
|
||||||
If they are not cached, it collects the parameters from a designated
|
If they are not cached, it collects the parameters from a designated
|
||||||
configuration source, formats their keys to lowercase, and then stores
|
configuration source, formats their keys to lowercase, and then stores
|
||||||
them in the cache for a limited period.
|
them in the cache for a limited period.
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: A dictionary containing the project parameters with lowercase keys.
|
|
||||||
"""
|
"""
|
||||||
parameters = cache.get("parameters", {})
|
parameters = cache.get("parameters", {})
|
||||||
|
|
||||||
|
|
@ -197,19 +141,11 @@ def get_project_parameters() -> dict:
|
||||||
return parameters
|
return parameters
|
||||||
|
|
||||||
|
|
||||||
def resolve_translations_for_elasticsearch(instance, field_name) -> None:
|
def resolve_translations_for_elasticsearch(instance, field_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
Resolves translations for a given field in an Elasticsearch-compatible
|
Resolves translations for a given field in an Elasticsearch-compatible
|
||||||
format. It checks if the localized version of the field contains data,
|
format. It checks if the localized version of the field contains data,
|
||||||
and if not, sets it to the value of the default field.
|
and if not, sets it to the value of the default field.
|
||||||
|
|
||||||
Parameters:
|
|
||||||
instance: The object instance containing the field to resolve.
|
|
||||||
field_name (str): The base name of the field for which translations
|
|
||||||
are being resolved.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
None
|
|
||||||
"""
|
"""
|
||||||
field = getattr(instance, f"{field_name}_{LANGUAGE_CODE}", "")
|
field = getattr(instance, f"{field_name}_{LANGUAGE_CODE}", "")
|
||||||
filled_field = getattr(instance, field_name, "")
|
filled_field = getattr(instance, field_name, "")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import BadRequest
|
from django.core.exceptions import BadRequest
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from graphene import Context
|
||||||
|
from rest_framework.request import Request
|
||||||
|
|
||||||
from evibes.settings import UNSAFE_CACHE_KEYS
|
from evibes.settings import UNSAFE_CACHE_KEYS
|
||||||
from vibes_auth.models import User
|
from vibes_auth.models import User
|
||||||
|
|
@ -26,7 +31,9 @@ def get_cached_value(user: User, key: str, default=None) -> None | object:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def set_cached_value(user: User, key: str, value: object, timeout: int = 3600) -> None | object:
|
def set_cached_value(
|
||||||
|
user: User | AbstractBaseUser | AnonymousUser, key: str, value: object, timeout: int = 3600
|
||||||
|
) -> None | object:
|
||||||
if user.is_staff or user.is_superuser:
|
if user.is_staff or user.is_superuser:
|
||||||
cache.set(key, value, timeout)
|
cache.set(key, value, timeout)
|
||||||
return value
|
return value
|
||||||
|
|
@ -34,7 +41,7 @@ def set_cached_value(user: User, key: str, value: object, timeout: int = 3600) -
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def web_cache(request, key, data, timeout):
|
def web_cache(request: Request | Context, key: str, data: dict[str, Any], timeout: int):
|
||||||
if not data and not timeout:
|
if not data and not timeout:
|
||||||
return {"data": get_cached_value(request.user, key)}
|
return {"data": get_cached_value(request.user, key)}
|
||||||
if (data and not timeout) or (timeout and not data):
|
if (data and not timeout) or (timeout and not data):
|
||||||
|
|
@ -44,7 +51,7 @@ def web_cache(request, key, data, timeout):
|
||||||
return {"data": set_cached_value(request.user, key, data, timeout)}
|
return {"data": set_cached_value(request.user, key, data, timeout)}
|
||||||
|
|
||||||
|
|
||||||
def set_default_cache():
|
def set_default_cache() -> None:
|
||||||
data_dir = Path(__file__).resolve().parent.parent / "data"
|
data_dir = Path(__file__).resolve().parent.parent / "data"
|
||||||
for json_file in data_dir.glob("*.json"):
|
for json_file in data_dir.glob("*.json"):
|
||||||
with json_file.open("r", encoding="utf-8") as f:
|
with json_file.open("r", encoding="utf-8") as f:
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import re
|
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.files.images import get_image_dimensions
|
from django.core.files.images import ImageFile, get_image_dimensions
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
def validate_category_image_dimensions(image):
|
def validate_category_image_dimensions(image: ImageFile) -> None:
|
||||||
max_width = 99999
|
max_width = 99999
|
||||||
max_height = 99999
|
max_height = 99999
|
||||||
|
|
||||||
|
|
@ -14,9 +12,3 @@ def validate_category_image_dimensions(image):
|
||||||
|
|
||||||
if width > max_width or height > max_height:
|
if width > max_width or height > max_height:
|
||||||
raise ValidationError(_(f"image dimensions should not exceed w{max_width} x h{max_height} pixels"))
|
raise ValidationError(_(f"image dimensions should not exceed w{max_width} x h{max_height} pixels"))
|
||||||
|
|
||||||
|
|
||||||
def validate_phone_number(value, **_kwargs):
|
|
||||||
phone_regex = re.compile(r"^\+?1?\d{9,15}$")
|
|
||||||
if not phone_regex.match(value):
|
|
||||||
raise ValidationError(_("invalid phone number format"))
|
|
||||||
|
|
|
||||||
9
core/vendors/__init__.py
vendored
9
core/vendors/__init__.py
vendored
|
|
@ -5,6 +5,7 @@ from math import ceil, log10
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from django.db import IntegrityError, transaction
|
from django.db import IntegrityError, transaction
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
from core.elasticsearch import process_system_query
|
from core.elasticsearch import process_system_query
|
||||||
from core.models import (
|
from core.models import (
|
||||||
|
|
@ -235,7 +236,7 @@ class AbstractVendor:
|
||||||
if not rate:
|
if not rate:
|
||||||
raise RatesError(f"No rate found for {currency or self.currency} in {rates} with probider {provider}...")
|
raise RatesError(f"No rate found for {currency or self.currency} in {rates} with probider {provider}...")
|
||||||
|
|
||||||
return float(round(price / rate, 2)) if rate else round(price, 2)
|
return float(round(price / rate, 2)) if rate else float(round(price, 2)) # type: ignore [arg-type]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def round_price_marketologically(price: float) -> float:
|
def round_price_marketologically(price: float) -> float:
|
||||||
|
|
@ -282,13 +283,13 @@ class AbstractVendor:
|
||||||
def get_products(self) -> None:
|
def get_products(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_products_queryset(self):
|
def get_products_queryset(self) -> QuerySet[Product]:
|
||||||
return Product.objects.filter(stocks__vendor=self.get_vendor_instance(), orderproduct__isnull=True)
|
return Product.objects.filter(stocks__vendor=self.get_vendor_instance(), orderproduct__isnull=True)
|
||||||
|
|
||||||
def get_stocks_queryset(self):
|
def get_stocks_queryset(self) -> QuerySet[Stock]:
|
||||||
return Stock.objects.filter(product__in=self.get_products_queryset(), product__orderproduct__isnull=True)
|
return Stock.objects.filter(product__in=self.get_products_queryset(), product__orderproduct__isnull=True)
|
||||||
|
|
||||||
def get_attribute_values_queryset(self):
|
def get_attribute_values_queryset(self) -> QuerySet[AttributeValue]:
|
||||||
return AttributeValue.objects.filter(
|
return AttributeValue.objects.filter(
|
||||||
product__in=self.get_products_queryset(), product__orderproduct__isnull=True
|
product__in=self.get_products_queryset(), product__orderproduct__isnull=True
|
||||||
)
|
)
|
||||||
|
|
|
||||||
300
core/views.py
300
core/views.py
|
|
@ -8,7 +8,7 @@ from django.contrib.sitemaps.views import index as _sitemap_index_view
|
||||||
from django.contrib.sitemaps.views import sitemap as _sitemap_detail_view
|
from django.contrib.sitemaps.views import sitemap as _sitemap_detail_view
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import BadRequest
|
from django.core.exceptions import BadRequest
|
||||||
from django.http import FileResponse, Http404, JsonResponse
|
from django.http import FileResponse, Http404, JsonResponse, HttpRequest, HttpResponseRedirect
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.http import urlsafe_base64_decode
|
from django.utils.http import urlsafe_base64_decode
|
||||||
|
|
@ -24,6 +24,7 @@ from graphene_file_upload.django import FileUploadGraphQLView
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.renderers import MultiPartRenderer
|
from rest_framework.renderers import MultiPartRenderer
|
||||||
|
from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework_xml.renderers import XMLRenderer
|
from rest_framework_xml.renderers import XMLRenderer
|
||||||
|
|
@ -61,74 +62,40 @@ logger = logging.getLogger("django")
|
||||||
@cache_page(60 * 60 * 12)
|
@cache_page(60 * 60 * 12)
|
||||||
@vary_on_headers("Host")
|
@vary_on_headers("Host")
|
||||||
def sitemap_index(request, *args, **kwargs):
|
def sitemap_index(request, *args, **kwargs):
|
||||||
"""
|
|
||||||
Handles the request for the sitemap index and returns an XML response. It ensures the response includes
|
|
||||||
the appropriate content type header for XML.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The HTTP request object.
|
|
||||||
*args: Additional positional arguments passed to the view.
|
|
||||||
**kwargs: Additional keyword arguments passed to the view.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A response object containing the sitemap index in XML format, with the proper content type set as
|
|
||||||
"application/xml; charset=utf-8".
|
|
||||||
"""
|
|
||||||
response = _sitemap_index_view(request, *args, **kwargs)
|
response = _sitemap_index_view(request, *args, **kwargs)
|
||||||
response["Content-Type"] = "application/xml; charset=utf-8"
|
response["Content-Type"] = "application/xml; charset=utf-8"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
sitemap_index.__doc__ = _( # type: ignore [assignment]
|
||||||
|
"Handles the request for the sitemap index and returns an XML response. "
|
||||||
|
"It ensures the response includes the appropriate content type header for XML."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@cache_page(60 * 60 * 24)
|
@cache_page(60 * 60 * 24)
|
||||||
@vary_on_headers("Host")
|
@vary_on_headers("Host")
|
||||||
def sitemap_detail(request, *args, **kwargs):
|
def sitemap_detail(request, *args, **kwargs):
|
||||||
"""
|
|
||||||
Handles the detailed view response for a sitemap. This function processes
|
|
||||||
the request, fetches the appropriate sitemap detail response, and sets the
|
|
||||||
Content-Type header for XML responses.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: An HTTP request object containing request metadata, such as
|
|
||||||
headers and HTTP method.
|
|
||||||
*args: Additional positional arguments provided dynamically to the
|
|
||||||
underlying sitemap detail view function.
|
|
||||||
**kwargs: Additional keyword arguments provided dynamically to the
|
|
||||||
underlying sitemap detail view function.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
HttpResponse: A response object with content representing the requested
|
|
||||||
sitemap details. The Content-Type header is explicitly set to
|
|
||||||
"application/xml; charset=utf-8".
|
|
||||||
"""
|
|
||||||
response = _sitemap_detail_view(request, *args, **kwargs)
|
response = _sitemap_detail_view(request, *args, **kwargs)
|
||||||
response["Content-Type"] = "application/xml; charset=utf-8"
|
response["Content-Type"] = "application/xml; charset=utf-8"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
sitemap_detail.__doc__ = _( # type: ignore [assignment]
|
||||||
|
"Handles the detailed view response for a sitemap. "
|
||||||
|
"This function processes the request, fetches the appropriate "
|
||||||
|
"sitemap detail response, and sets the Content-Type header for XML."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CustomGraphQLView(FileUploadGraphQLView):
|
class CustomGraphQLView(FileUploadGraphQLView):
|
||||||
"""
|
|
||||||
A custom GraphQL view class that extends the functionality of FileUploadGraphQLView.
|
|
||||||
|
|
||||||
This class serves as a customization extension of FileUploadGraphQLView that allows modification
|
|
||||||
or enhancement of specific behaviors, particularly the context handling for GraphQL requests.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_context(self, request):
|
def get_context(self, request):
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
|
||||||
class CustomSwaggerView(SpectacularSwaggerView):
|
class CustomSwaggerView(SpectacularSwaggerView):
|
||||||
"""
|
|
||||||
CustomSwaggerView is a subclass of SpectacularSwaggerView.
|
|
||||||
|
|
||||||
This class overrides the `get_context_data` method to
|
|
||||||
add extra context to the response. It modifies the context by
|
|
||||||
including the absolute URI of the current request as the `script_url`.
|
|
||||||
This can be useful in scenarios where the script or reference
|
|
||||||
URL needs to be dynamically generated and included in the context.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
@ -137,16 +104,6 @@ class CustomSwaggerView(SpectacularSwaggerView):
|
||||||
|
|
||||||
|
|
||||||
class CustomRedocView(SpectacularRedocView):
|
class CustomRedocView(SpectacularRedocView):
|
||||||
"""
|
|
||||||
CustomRedocView provides a customized version of the SpectacularRedocView.
|
|
||||||
|
|
||||||
This class extends the SpectacularRedocView to include additional
|
|
||||||
functionality, such as dynamically setting the `script_url` in the
|
|
||||||
context data. It is designed to be used where customized behavior
|
|
||||||
for rendering ReDoc UI is required, specifically adapting the script
|
|
||||||
URL for the current request environment.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
@ -156,24 +113,7 @@ class CustomRedocView(SpectacularRedocView):
|
||||||
|
|
||||||
@extend_schema_view(**LANGUAGE_SCHEMA)
|
@extend_schema_view(**LANGUAGE_SCHEMA)
|
||||||
class SupportedLanguagesView(APIView):
|
class SupportedLanguagesView(APIView):
|
||||||
"""
|
__doc__ = _("Returns a list of supported languages and their corresponding information.") # type: ignore [assignment]
|
||||||
Handles retrieving the list of supported languages.
|
|
||||||
|
|
||||||
This class provides an endpoint to return information about available languages.
|
|
||||||
It is configured with relevant serializers, permission classes, and renderers
|
|
||||||
for flexibility in response formats and access permissions. The endpoint
|
|
||||||
supports retrieving the list of languages with their respective codes, names,
|
|
||||||
and flags.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
serializer_class (Serializer): Serializer used for formatting the response data.
|
|
||||||
permission_classes (list): Permissions applied to restrict the endpoint access.
|
|
||||||
renderer_classes (list): Renderers available for formatting response output.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
get(self, request): Retrieves the list of supported languages.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
serializer_class = LanguageSerializer
|
serializer_class = LanguageSerializer
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
|
|
@ -186,7 +126,7 @@ class SupportedLanguagesView(APIView):
|
||||||
YAMLRenderer,
|
YAMLRenderer,
|
||||||
]
|
]
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request: Request, *args, **kwargs) -> Response:
|
||||||
return Response(
|
return Response(
|
||||||
data=self.serializer_class(
|
data=self.serializer_class(
|
||||||
[
|
[
|
||||||
|
|
@ -205,30 +145,7 @@ class SupportedLanguagesView(APIView):
|
||||||
|
|
||||||
@extend_schema_view(**PARAMETERS_SCHEMA)
|
@extend_schema_view(**PARAMETERS_SCHEMA)
|
||||||
class WebsiteParametersView(APIView):
|
class WebsiteParametersView(APIView):
|
||||||
"""
|
__doc__ = _("Returns the parameters of the website as a JSON object.") # type: ignore [assignment]
|
||||||
Handles operations related to website parameters.
|
|
||||||
|
|
||||||
This class is a Django Rest Framework view that allows clients to retrieve
|
|
||||||
the parameters of a website. It uses different renderers to present the data
|
|
||||||
in various formats. The view is publicly accessible.
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
serializer_class
|
|
||||||
A placeholder for a DRF serializer, it is set to None since no serializer
|
|
||||||
is explicitly used in this view.
|
|
||||||
permission_classes
|
|
||||||
A list indicating the permissions required to access this view. In this case,
|
|
||||||
`AllowAny`, meaning the view is open to everyone.
|
|
||||||
renderer_classes
|
|
||||||
A list of renderers available for this view, supporting CamelCase JSON,
|
|
||||||
multipart forms, XML, and YAML formats.
|
|
||||||
|
|
||||||
Methods
|
|
||||||
-------
|
|
||||||
get(request)
|
|
||||||
Handles HTTP GET requests to fetch website parameters.
|
|
||||||
"""
|
|
||||||
|
|
||||||
serializer_class = None
|
serializer_class = None
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
|
|
@ -241,30 +158,13 @@ class WebsiteParametersView(APIView):
|
||||||
YAMLRenderer,
|
YAMLRenderer,
|
||||||
]
|
]
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request: Request, *args, **kwargs) -> Response:
|
||||||
return Response(data=camelize(get_project_parameters()), status=status.HTTP_200_OK)
|
return Response(data=camelize(get_project_parameters()), status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_view(**CACHE_SCHEMA)
|
@extend_schema_view(**CACHE_SCHEMA)
|
||||||
class CacheOperatorView(APIView):
|
class CacheOperatorView(APIView):
|
||||||
"""
|
__doc__ = _("Handles cache operations such as reading and setting cache data with a specified key and timeout.") # type: ignore [assignment]
|
||||||
View for managing cache operations.
|
|
||||||
|
|
||||||
This class provides an API view for handling cache operations such as setting cache
|
|
||||||
data with a specified key and timeout. It leverages multiple renderer classes for
|
|
||||||
serializing outputs in various formats.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
serializer_class (type): Serializer to validate and deserialize input data.
|
|
||||||
permission_classes (list): List of permission classes to apply access
|
|
||||||
restrictions.
|
|
||||||
renderer_classes (list): List of renderer classes to serialize the output
|
|
||||||
in desired formats.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
post(request, *args, **kwargs): Handles HTTP POST requests to set cache
|
|
||||||
data based on the provided key and timeout.
|
|
||||||
"""
|
|
||||||
|
|
||||||
serializer_class = CacheOperatorSerializer
|
serializer_class = CacheOperatorSerializer
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
|
|
@ -277,7 +177,7 @@ class CacheOperatorView(APIView):
|
||||||
YAMLRenderer,
|
YAMLRenderer,
|
||||||
]
|
]
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request: Request, *args, **kwargs) -> Response:
|
||||||
return Response(
|
return Response(
|
||||||
data=web_cache(
|
data=web_cache(
|
||||||
request,
|
request,
|
||||||
|
|
@ -291,22 +191,7 @@ class CacheOperatorView(APIView):
|
||||||
|
|
||||||
@extend_schema_view(**CONTACT_US_SCHEMA)
|
@extend_schema_view(**CONTACT_US_SCHEMA)
|
||||||
class ContactUsView(APIView):
|
class ContactUsView(APIView):
|
||||||
"""
|
__doc__ = _("Handles `contact us` form submissions.") # type: ignore [assignment]
|
||||||
Handles contact us form submissions via a REST API.
|
|
||||||
|
|
||||||
This view processes user submissions for a "Contact Us" form. It validates the received
|
|
||||||
data using a serializer, applies rate limiting for IP-based requests, and sends emails
|
|
||||||
asynchronously. The view is prepared to handle multiple response formats using configured
|
|
||||||
renderers.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
serializer_class: The serializer class used to validate incoming data.
|
|
||||||
renderer_classes: A list of renderers to support multiple response formats.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
post: Handles POST requests to process form submissions.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
serializer_class = ContactUsSerializer
|
serializer_class = ContactUsSerializer
|
||||||
renderer_classes = [
|
renderer_classes = [
|
||||||
|
|
@ -317,7 +202,7 @@ class ContactUsView(APIView):
|
||||||
]
|
]
|
||||||
|
|
||||||
@method_decorator(ratelimit(key="ip", rate="2/h", method="POST", block=True))
|
@method_decorator(ratelimit(key="ip", rate="2/h", method="POST", block=True))
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request: Request, *args, **kwargs) -> Response:
|
||||||
serializer = self.serializer_class(data=request.data)
|
serializer = self.serializer_class(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
contact_us_email.delay(serializer.validated_data)
|
contact_us_email.delay(serializer.validated_data)
|
||||||
|
|
@ -327,20 +212,7 @@ class ContactUsView(APIView):
|
||||||
|
|
||||||
@extend_schema_view(**REQUEST_CURSED_URL_SCHEMA)
|
@extend_schema_view(**REQUEST_CURSED_URL_SCHEMA)
|
||||||
class RequestCursedURLView(APIView):
|
class RequestCursedURLView(APIView):
|
||||||
"""
|
__doc__ = _("Handles requests for processing and validating URLs from incoming POST requests.") # type: ignore [assignment]
|
||||||
Handles requests for processing and validating URLs from incoming POST requests.
|
|
||||||
|
|
||||||
Particularly intended for validating and processing URLs provided by clients. It uses rate-limiting, caching, and
|
|
||||||
various response format renderers to optimize performance and ensure safe handling of external data.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
permission_classes (list): Specifies the permissions required to access this view.
|
|
||||||
renderer_classes (list): Configures the response format renderers available for this view.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
post: Handles the POST request to validate the URL, fetches its data if valid,
|
|
||||||
and returns the processed response.
|
|
||||||
"""
|
|
||||||
|
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
AllowAny,
|
AllowAny,
|
||||||
|
|
@ -353,7 +225,7 @@ class RequestCursedURLView(APIView):
|
||||||
]
|
]
|
||||||
|
|
||||||
@method_decorator(ratelimit(key="ip", rate="10/h"))
|
@method_decorator(ratelimit(key="ip", rate="10/h"))
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request: Request, *args, **kwargs) -> Response:
|
||||||
url = request.data.get("url")
|
url = request.data.get("url")
|
||||||
if not is_url_safe(url):
|
if not is_url_safe(url):
|
||||||
return Response(
|
return Response(
|
||||||
|
|
@ -380,23 +252,7 @@ class RequestCursedURLView(APIView):
|
||||||
|
|
||||||
@extend_schema_view(**SEARCH_SCHEMA)
|
@extend_schema_view(**SEARCH_SCHEMA)
|
||||||
class GlobalSearchView(APIView):
|
class GlobalSearchView(APIView):
|
||||||
"""
|
__doc__ = _("Handles global search queries.") # type: ignore [assignment]
|
||||||
Class-based view for handling global search functionality.
|
|
||||||
|
|
||||||
This class is designed to process search queries from HTTP GET requests. It is
|
|
||||||
capable of rendering results in multiple formats including CamelCase JSON,
|
|
||||||
MultiPart, XML, and YAML. The class uses a custom schema for API documentation
|
|
||||||
and processes search queries passed as parameters in the request.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
renderer_classes (list): List of renderer classes used to serialize responses
|
|
||||||
into various formats such as CamelCase JSON, MultiPart, XML, and YAML.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
get: Handles HTTP GET requests by processing the search query and returning
|
|
||||||
formatted search results.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
renderer_classes = [
|
renderer_classes = [
|
||||||
CamelCaseJSONRenderer,
|
CamelCaseJSONRenderer,
|
||||||
|
|
@ -405,31 +261,17 @@ class GlobalSearchView(APIView):
|
||||||
YAMLRenderer,
|
YAMLRenderer,
|
||||||
]
|
]
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request: Request, *args, **kwargs) -> Response:
|
||||||
return Response(camelize({"results": process_query(query=request.GET.get("q", "").strip(), request=request)}))
|
return Response(camelize({"results": process_query(query=request.GET.get("q", "").strip(), request=request)}))
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_view(**BUY_AS_BUSINESS_SCHEMA)
|
@extend_schema_view(**BUY_AS_BUSINESS_SCHEMA)
|
||||||
class BuyAsBusinessView(APIView):
|
class BuyAsBusinessView(APIView):
|
||||||
"""
|
__doc__ = _("Handles the logic of buying as a business without registration.") # type: ignore [assignment]
|
||||||
View for buying as a business.
|
|
||||||
|
|
||||||
This view handles the logic of creating orders and processing transactions when a
|
|
||||||
business makes a purchase. It ensures that the request data is properly validated
|
|
||||||
and processed, handles the creation of the order, and starts the transaction process.
|
|
||||||
The view also restricts the rate of requests based on the client's IP address
|
|
||||||
to prevent abuse.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
schema (class): Extended schema for API documentation.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
post(request, *_args, **kwargs):
|
|
||||||
Handles the "POST" request to process a business purchase.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
@method_decorator(ratelimit(key="ip", rate="10/h" if not settings.DEBUG else "888/h"))
|
@method_decorator(ratelimit(key="ip", rate="10/h" if not settings.DEBUG else "888/h"))
|
||||||
def post(self, request, *_args, **kwargs):
|
def post(self, request: Request, *args, **kwargs) -> Response:
|
||||||
serializer = BuyAsBusinessOrderSerializer(data=request.data)
|
serializer = BuyAsBusinessOrderSerializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
order = Order.objects.create(status="MOMENTAL")
|
order = Order.objects.create(status="MOMENTAL")
|
||||||
|
|
@ -459,26 +301,7 @@ class BuyAsBusinessView(APIView):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def download_digital_asset_view(request, *args, **kwargs):
|
def download_digital_asset_view(request: HttpRequest, *args, **kwargs) -> FileResponse | JsonResponse:
|
||||||
"""
|
|
||||||
Handles the downloading of a digital asset associated with an order. Ensures that users
|
|
||||||
are permitted to download the asset only once. Validates the request, retrieves the file,
|
|
||||||
and serves it as a downloadable response. Returns appropriate error responses for different
|
|
||||||
failure scenarios.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The HTTP request object containing information about the client request.
|
|
||||||
*args: Additional positional arguments.
|
|
||||||
**kwargs: Additional keyword arguments.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
BadRequest: If the digital asset has already been downloaded.
|
|
||||||
DigitalAssetDownload.DoesNotExist: If the requested digital asset cannot be found.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A FileResponse containing the digital asset file if the request is valid. Returns
|
|
||||||
a JsonResponse with an error message if an error occurs during the process.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
logger.debug(f"download_digital_asset_view: {kwargs}")
|
logger.debug(f"download_digital_asset_view: {kwargs}")
|
||||||
uuid = urlsafe_base64_decode(str(kwargs.get("order_product_uuid"))).decode("utf-8")
|
uuid = urlsafe_base64_decode(str(kwargs.get("order_product_uuid"))).decode("utf-8")
|
||||||
|
|
@ -488,6 +311,9 @@ def download_digital_asset_view(request, *args, **kwargs):
|
||||||
if download.num_downloads >= 1:
|
if download.num_downloads >= 1:
|
||||||
raise BadRequest(_("you can only download the digital asset once"))
|
raise BadRequest(_("you can only download the digital asset once"))
|
||||||
|
|
||||||
|
if download.order_product.status != "FINISHED":
|
||||||
|
raise BadRequest(_("the order must be paid before downloading the digital asset"))
|
||||||
|
|
||||||
download.num_downloads += 1
|
download.num_downloads += 1
|
||||||
download.save()
|
download.save()
|
||||||
|
|
||||||
|
|
@ -522,24 +348,16 @@ def download_digital_asset_view(request, *args, **kwargs):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def favicon_view(request, *args, **kwargs):
|
# noinspection PyTypeChecker
|
||||||
"""
|
download_digital_asset_view.__doc__ = _( # type: ignore [assignment]
|
||||||
Handles requests for the favicon of a website. This function attempts to serve the favicon
|
"Handles the downloading of a digital asset associated with an order.\n"
|
||||||
file located in the static directory of the project. If the favicon file is not found,
|
"This function attempts to serve the digital asset file located in the "
|
||||||
an HTTP 404 error is raised to indicate the resource is unavailable.
|
"storage directory of the project. If the file is not found, an HTTP 404 "
|
||||||
|
"error is raised to indicate the resource is unavailable."
|
||||||
|
)
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The HTTP request object.
|
|
||||||
*args: Additional positional arguments that are ignored in this function.
|
|
||||||
**kwargs: Additional keyword arguments that are ignored in this function.
|
|
||||||
|
|
||||||
Returns:
|
def favicon_view(request: HttpRequest, *args, **kwargs) -> FileResponse | Http404:
|
||||||
FileResponse: A file response containing the favicon image with the content-type
|
|
||||||
"image/x-icon".
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Http404: Raised if the favicon file is not found.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
favicon_path = os.path.join(settings.BASE_DIR, "static/favicon.png")
|
favicon_path = os.path.join(settings.BASE_DIR, "static/favicon.png")
|
||||||
return FileResponse(open(favicon_path, "rb"), content_type="image/x-icon")
|
return FileResponse(open(favicon_path, "rb"), content_type="image/x-icon")
|
||||||
|
|
@ -547,20 +365,22 @@ def favicon_view(request, *args, **kwargs):
|
||||||
raise Http404(_("favicon not found")) from fnfe
|
raise Http404(_("favicon not found")) from fnfe
|
||||||
|
|
||||||
|
|
||||||
def index(request, *args, **kwargs):
|
# noinspection PyTypeChecker
|
||||||
"""
|
favicon_view.__doc__ = _( # type: ignore [assignment]
|
||||||
Redirects the request to the admin index page.
|
"Handles requests for the favicon of a website.\n"
|
||||||
|
"This function attempts to serve the favicon file located in the static directory of the project. "
|
||||||
|
"If the favicon file is not found, an HTTP 404 error is raised to indicate the resource is unavailable."
|
||||||
|
)
|
||||||
|
|
||||||
The function handles incoming HTTP requests and redirects them to the Django
|
|
||||||
admin interface index page. It uses Django's `redirect` function for handling
|
|
||||||
the HTTP redirection.
|
|
||||||
|
|
||||||
Args:
|
def index(request: HttpRequest, *args, **kwargs) -> HttpResponseRedirect:
|
||||||
request: The HttpRequest object representing the incoming request.
|
|
||||||
*args: Additional positional arguments, if any.
|
|
||||||
**kwargs: Additional keyword arguments, if any.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
HttpResponseRedirect: An HTTP response that redirects to the admin index.
|
|
||||||
"""
|
|
||||||
return redirect("admin:index")
|
return redirect("admin:index")
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
index.__doc__ = _( # type: ignore [assignment]
|
||||||
|
"Redirects the request to the admin index page. "
|
||||||
|
"The function handles incoming HTTP requests and redirects them to the Django "
|
||||||
|
"admin interface index page. It uses Django's `redirect` function for handling "
|
||||||
|
"the HTTP redirection."
|
||||||
|
)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue